tag:blogger.com,1999:blog-144756962024-03-06T04:22:46.939+08:00Work noteThings of workAlan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.comBlogger180125tag:blogger.com,1999:blog-14475696.post-81238988083824136702018-06-08T22:36:00.001+08:002018-06-08T22:36:49.874+08:00MySQL IN 參數在 Go 的正確用法<p dir="ltr">使用 <a href="https://github.com/go-sql-driver/mysql">go-sql-driver/mysql</a> 操作資料庫,一個場景是查詢,使用 <a href="https://dev.mysql.com/doc/refman/8.0/en/comparison-operators.html#function_in">IN 的語法</a>。但是結果不如預期,原本以為踩到上游的地雷,找到 <a href="https://github.com/go-sql-driver/mysql/issues/540">#540 cannot update multiple data</a>,<a href="https://github.com/go-sql-driver/mysql/issues/540#issuecomment-274311791">INADA Naoki</a><br>
解釋參數被解讀成字串,不是原本預期的結果。</p>
<p dir="ltr">追了 database/sql,看到最後的解釋 <a href="https://golang.org/src/database/sql/driver/types.go#L233">src/database/sql/driver/types.go</a>,,參數的類型一旦是 string,值被當成 string 返回。所以呼應 INADA 的解釋。</p>
<p dir="ltr">ConvertValues() 的代碼裡無法接受 IN 參數帶入。做了實驗得出結論,得自己組合語句。</p>
Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com0tag:blogger.com,1999:blog-14475696.post-59232053826119975662015-11-27T11:20:00.001+08:002015-11-27T11:20:19.907+08:00MySQL Slave 重啟後步驟此文章的場景是描述 MySQL Slave 和 Master 斷了同步資料,如何恢復。<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://drchadedwards.com/wp-content/uploads/2011/09/prolotherapy-ligament-steel-cable-broken.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://drchadedwards.com/wp-content/uploads/2011/09/prolotherapy-ligament-steel-cable-broken.jpg" height="173" width="400" /></a></div>
<div>
<br /></div>
<div>
<ol>
<li>[M] <span style="font-family: Courier New, Courier, monospace;">myql> FLUSH TABLES WITH READ LOCK;</span></li>
<li>[M] <span style="font-family: Courier New, Courier, monospace;">$ mysqldump --all-databases --master-data | bzip2 -9 > mysql.bz2</span></li>
<li><span style="font-family: inherit;">[M] </span><span style="font-family: Courier New, Courier, monospace;">scp mysql.bz2 foo@SLAVE:</span></li>
<li><span style="font-family: inherit;">[S] </span><span style="font-family: Courier New, Courier, monospace;">mysql> STOP SLAVE;</span></li>
<li><span style="font-family: inherit;">[S] </span><span style="font-family: Courier New, Courier, monospace;">bzip2 -dc | mysql -u root -p</span></li>
<li><span style="font-family: inherit;">[M] </span><span style="font-family: Courier New, Courier, monospace;">mysql> RESET MASTER;</span></li>
<li><span style="font-family: inherit;">[S] </span><span style="font-family: Courier New, Courier, monospace;">mysql> CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=147;</span></li>
<li><span style="font-family: inherit;">[S] </span><span style="font-family: Courier New, Courier, monospace;">mysql> START SLAVE;</span></li>
<li><span style="font-family: inherit;">[M] </span><span style="font-family: Courier New, Courier, monospace;">UNLOCK TABLES;</span></li>
</ol>
</div>
Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com0tag:blogger.com,1999:blog-14475696.post-80389630226933587812015-10-04T22:59:00.001+08:002015-10-04T22:59:16.282+08:00WordPress Replication手上有兩台異地不同 Public IP 主機,在 CloudFlare 設定 DNS Round Robin,又運行著 WordPress,下面解說如何設定兩台主機同步。讓兩台主機都能登入,且新文章能互相同步。<br />
<div>
<br /></div>
<h2>
MySQL 資料庫</h2>
<div>
參考 <a href="http://dev.mysql.com/doc/refman/5.6/en/replication.html" target="_blank">MySQL Replication</a> 設定。要注意的是因為做的是 DNS Round Robin,所以隨機兩台主機都要設定 master-slave 兩種角色同時運行,我參考 <a href="http://how%20to%20set%20up%20mysql%20master-master%20replication/" target="_blank">Digital Ocean</a> 的文章完成。</div>
<div>
<br /></div>
<h2>
同步腳本</h2>
<div>
因為 WordPress 要處理 cache、files 資料夾,腳本請參閱 <a href="http://a2n-work.blogspot.com/2015/10/ftp-replication.html" target="_blank">FTP Replication</a>。</div>
Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com0tag:blogger.com,1999:blog-14475696.post-7545257654506901772015-10-04T22:58:00.000+08:002015-10-04T22:58:16.012+08:00FTP Replication我有兩台異地不同 Public IP 主機,在 Cloud Flare 設定 Round Robin,運行著 nginx。此文講解使用兩個腳本同步檔案。<br />
<div>
<br /></div>
<div>
我的 H0 機器讓人 FTP 上傳檔案,監控程式偵測有檔案異動及開始 rsync 到 H1。示意圖如下:</div>
<div>
<br /></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://docs.google.com/drawings/d/185qTFchbXPPgOX3eqLToqfOC6bO4BdeNWKqPdraI59w/pub?w=480&h=360" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://docs.google.com/drawings/d/185qTFchbXPPgOX3eqLToqfOC6bO4BdeNWKqPdraI59w/pub?w=480&h=360" /></a></div>
<div>
<br /></div>
<h2>
H0</h2>
<div>
<script src="https://gist.github.com/a2n/b0490cdf643fb88dc533.js"></script></div>
<div>
<br />
L3 ~ L6: 因為 web root 權限需要,所以使用 sudo 提高權限。<br />
L8: H0 & H1 透過 ssh 加密傳輸,得事先加信任公鑰。
L14 ~ L15: inotifywait 排除掉不想監控的檔案 ([Tt]hunms.db),接著只監控特定事件 (delete, moved_to, close_write, create)。為了記錄過程我把時間戳一並寫出,log 的樣子會長這樣:</div>
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">15/10/04 21:37:05 CREATE /var/www/example.com/index.html</span></blockquote>
<div style="margin: 0px;">
L9: 在 H1 機器上有個 pool 目錄放置這些需要同步的檔案,原因不想讓 rsync 直接寫到 web root,權限過大危險。<br />
L21: 移除前綴字,避免同步路徑錯誤。<br />
L24: 移除檔案名稱,讓 rsync 同步資料夾,而非單一檔案。<br />
L26: rsync + ssh 同步資料夾到 H1。<br />
<br /></div>
<h2>
H1</h2>
<div>
<script src="https://gist.github.com/a2n/a28b60315eeb481f5b43.js"></script><br />
L3 ~ L6: 因為要寫入到 web root,要求得是 root 。<br />
L13 ~ L26: 做的事情和 H0 一樣,只是來源和目的互換。<br />
<br />
<h2>
已知問題</h2>
<h3>
刪除</h3>
<span style="font-family: Courier New, Courier, monospace;">inotifywait</span> 遇到刪除檔案或目錄,只會出現 <span style="font-family: Courier New, Courier, monospace;">OPEN,ISDIR</span>,接著就沒了,所以也無法偵測到 <span style="font-family: Courier New, Courier, monospace;">DELETE</span> 事件。rsync 直到下個時間才會把上個未刪除的工作做完。<br />
<br />
<br /></div>
Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com0tag:blogger.com,1999:blog-14475696.post-43444370526674350432015-10-02T10:39:00.000+08:002015-10-02T10:39:02.269+08:00GoDaddy 註冊系統有安全疑慮GoDaddy 註冊系統只接受最長 11 個字的 local-part,而 Email 地址的規範 <a href="https://tools.ietf.org/html/rfc5322#section-3.4.1" target="_blank">RFC 5322</a> 明確指出最長可以到 64 個字。<br />
<br />
<h2>
緣由</h2>
我在 GoDaddy 註冊了一個帳號,我的 Email local-part 有 30 個字,因為某個原因我需要重新登錄網站,結果就無法登錄。查了 Whois 發現 GoDaddy 把我的 Email 縮短了,而且是沒有規則。<br />
<br />
<h2>
客服</h2>
<h3>
0. 官網沒有文字客服</h3>
<div>
GoDaddy 不知緣由為何,停止了文字客服,只剩電話客服。因為擔心英文口說無法順利解決我的問題,且如此長的國際電話肯定所費不貲。最後讓我找到了 <a href="https://twitter.com/GoDaddyHelp" target="_blank">@GoDaddyHelp</a>。</div>
<div>
<br /></div>
<h3>
1. 英譯證件</h3>
<div>
GoDaddy 客服來信要求我提供英文翻譯的官方證件,原先試著自己 PS 將身分證翻譯成英文版本,但是客服不接受這種翻譯。後來我提供了護照,但是由於當初註冊使用的名字不是漢語拼音,而是沒有法律效力的自取英文名字。我在信中和對方表明當初我沒有想到註冊會失敗,且我的自取英文名字和漢語拼音的用處。客服人員基於保護客戶帳號安全,提供了三個方式:</div>
<div>
<br /></div>
<blockquote class="tr_bq">
0. 試著聯繫 Whois 上面錯誤的 Email。<br />1. 透過 ICANN <a href="http://www.icann.org/dndr/udrp/approved-providers.htm" target="_blank">投訴</a>。<br />2. <a href="http://www.godaddy.com/agreements/showdoc.aspx?pageid=CIVIL_SUBPOENA" target="_blank">法院傳票</a>要回。</blockquote>
<h3>
2. 將錯就錯</h3>
<div>
GoDaddy 客服拒絕我的護照證明後,我在信中嚴厲的反應這是網站註冊系統的瑕疵,造成我的困擾。客服根本不想回應我的理由,因為他有理由可以假設我是壞人,透過如此手段竊取別人的域名,想想也是有道理,就不在此爭端,徒勞罷。</div>
<div>
<br /></div>
<div>
我讀了 ICANN 投訴的方式,根據 2015-03-01 發佈的 <a href="https://www.icann.org/resources/pages/udrp-rules-2015-03-11-en" target="_blank">Rules for Uniform Domain Name Dispute Resolution Policy</a>,投訴方得負擔所有調查的費用,看了 <a href="https://www.godaddy.com/agreements/showdoc.aspx?pageid=CIVIL_SUBPOENA" target="_blank">GODADDY SUBPOENA POLICY/ATTORNEY TIPS</a> 光研究每小時就得付 75 USD,這已經超出我的域名購買費用,不划算。</div>
<div>
<br /></div>
<div>
最後,我想到了將錯就錯的伎倆,去申請 Whois 錯誤的 Email。因為是 Gmail 所以可以隨意申請,果真行得通,重置密碼的信件順利收到,把登入權限給拿回來了!</div>
<div>
<br /></div>
<div>
<br /></div>
<h2>
安全疑慮</h2>
<div>
一拿到登入權限後,試著在後台變更 Email 為 30 個字的帳號,發現依然不行,然後聯繫 @GoDaddyHelp,得到的答案是:</div>
<div>
<br /></div>
<blockquote class="tr_bq">
I was not able to duplicate this in another account. You may want to try using an alternate email address.</blockquote>
<br />
這種回答讓我對 GoDaddy 灰心,工程文化沒落實完全,如此簡單的註冊瑕疵能用這麼簡單的方式拿回權限,如果今天我就是壞人呢?<br />
Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com0tag:blogger.com,1999:blog-14475696.post-85576967367508908852015-09-01T10:26:00.000+08:002015-09-01T10:26:01.104+08:00事件捕捉進化最近寫<a href="https://github.com/a2n/crawler" target="_blank">網頁爬蟲</a>用到並行的方法,因為 golang 接收 channel 是外層包一個 <a href="https://talks.golang.org/2013/bestpractices.slide#28" target="_blank">for loop</a>,觀察到這樣會讓一個邏輯 CPU 使用率滿載,這個寫法是 <a href="https://en.wikipedia.org/wiki/Busy_waiting" target="_blank">busy waiting</a>,認為這麼做耗電很浪費資源。或許 golang 採用 <a href="https://golang.org/doc/faq#csp" target="_blank">CSP</a> channel 就是決定得走 busy waiting。<div>
<br /></div>
<div>
找到<a href="https://mail.haskell.org/pipermail/haskell/2011-April/022740.html" target="_blank">一篇</a> Haskell 討論 select(2) 或 poll(2) 捕捉方法,有人提出這些討論的視野都是較為底層,在 Haskell 可以用更高階優雅的方式解決。閱畢感到興奮,就是要優雅!</div>
Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com1tag:blogger.com,1999:blog-14475696.post-85655253175970041572014-10-08T17:18:00.004+08:002014-10-08T17:35:03.533+08:00iOS 安裝 in-house app 需要的網站<span style="font-family: inherit;">因為所處的 wifi 網路環境封鎖所有 outbound,要開放 iOS Enterprise Distribution 安裝所需的網路。修改了 iPhone wifi DNS server,得到以下記錄。</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<br />
<ol>
<li><span style="font-family: 'Courier New', Courier, monospace;">17-courier.push.apple.com</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">1-courier.push.apple.com</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">26-courier.push.apple.com</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">2-courier.push.apple.com</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">31-courier.push.apple.com</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">36-courier.push.apple.com</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">40-courier.push.apple.com</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">9-courier.push.apple.com</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">a1441.g4.akamai.net</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">a97.gi3.akamai.net</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">apple.com</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">apple-finance.query.yahoo.com</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">cl4.apple.com</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">e2842.e9.akamaiedge.net</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">init-p01st.push.apple.com</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">local</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">mesu.apple.com</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">p24-keyvalueservice.icloud.com</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">p24-keyvalueservice.icloud.com.akadns.net</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">setup.icloud.com</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">www.apple.com</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">www.isg-apple.com.akadns.net</span></li>
<li><span style="font-family: 'Courier New', Courier, monospace;">xp.apple.com</span></li>
</ol>
Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com0tag:blogger.com,1999:blog-14475696.post-76211743699905320532014-08-08T13:53:00.001+08:002014-08-08T13:53:12.137+08:00商工登記資料 API從<a href="https://play.google.com/store/apps/details?id=gov.gcis.inquery" target="_blank">商工登記公示查詢</a>得到靈感,取得 api 後,將文件寫在 <a href="https://docs.google.com/document/d/1bpcD8u-hnzEnKWnuWDIcOSrkgZQDOAYUh2opluvGP_Y/edit?usp=sharing" target="_blank">Google Drive</a>。<br />
Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com0tag:blogger.com,1999:blog-14475696.post-29218304299604984862014-05-14T10:53:00.002+08:002014-05-14T10:53:11.777+08:00CoreImage & GPUImage performanceThe benchmark suite numbers,<br />
<br />
<h4>
Specs</h4>
iPhone 5s<br />
iOS 7.1.1<br />
GPUImage 0.1.4<br />
<br />
<h4>
Still images</h4>
CPU 181.51ms<br />
Core Image 37.08ms<br />
GPUImage 49.62ms<br />
<br />
<h4>
Live video</h4>
CPU 15.77ms<br />
Core Image 3.20ms<br />
GPUImage 2.36msAlan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com0tag:blogger.com,1999:blog-14475696.post-25113084063919702652014-04-03T15:46:00.001+08:002014-04-03T15:54:30.200+08:00xcodebuild<a href="https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/xcodebuild.1.html" target="_blank">xcodebuild</a> is a command line that in charge of some actions in Xcode, like build, analyze, archive, test, installsrc, install and clear.<br />
<br />
<br />
Let says, I need release with a enterprise provision file, so here is the script,<br />
<iframe src="http://pastebin.com/embed_iframe.php?i=LepUmT76" style="border: none; height: 24em; width: 100%;"></iframe>
<br />
<br />Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com0tag:blogger.com,1999:blog-14475696.post-17637058561415359312014-02-07T17:31:00.003+08:002014-02-08T09:27:51.630+08:00iOS 免加 UUID 發佈方式以往都由 Apple 審核發佈 app,測試階段都是在自己的設備上,都能知道 UUID。目前做的 app 需要免加 UUID 任由安裝,Apple 稱為 <a href="https://developer.apple.com/support/ios/enterprise.html" target="_blank">in-house distribution</a>,能有此功能只有 <a href="https://developer.apple.com/programs/ios/enterprise/" target="_blank">iOS Developer Enterprise Program</a> 才做得到。Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com0tag:blogger.com,1999:blog-14475696.post-88473398059076899322013-12-18T22:29:00.000+08:002014-03-30T09:00:55.238+08:00IRC 紀錄即時推送<a class="tr_bq" href="http://irssi.org/" target="_blank">irssi</a> + <a href="https://github.com/rvoicilas/inotify-tools" target="_blank">inotify-tools</a> + <a href="http://git-scm.com/" target="_blank">git</a> 即時將紀錄推送到 <a href="https://github.com/" target="_blank">github</a>。<br />
<div>
<br /></div>
<h3>
Irssi</h3>
<div>
首先將 irssi 紀錄檔設定為每天切割:</div>
<blockquote class="tr_bq">
/log open -autoopen -targets #tcffm ~/irclogs/Freenode/#tcffm-%Y-%m-%d</blockquote>
<h3>
Git init</h3>
cd ~/irclogs/Freenode<br />
git init<br />
touch README<br />
git add README<br />
git commit -am "First commit."<br />
git remote add origin git@github.com:OOO/tcffm.git<br />
git push -u origin master<br />
<br />
<h3>
腳本</h3>
1. daily.sh<br />
此腳本使用 crontab 每天 0:00 啟動,內容如下:<br />
<blockquote class="tr_bq">
#!/bin/bash<br />
killall -9 inotifywait<br />
cd '/home/OOO/irclogs/Freenode'<br />
today=$(date +%Y-%m-%d)<br />
git add \#tcffm-$today<br />
inotifywait -qme modify --format "sh onchange.sh %w" \#tcffm-$today | sh</blockquote>
2. onchange.sh<br />
<blockquote>
#!/bin/bash<br />
git commit -am "log"<br />
git push </blockquote>
將兩個腳本權限設定為 755<br />
<br />
<h3>
啟動</h3>
執行 ~/irclogs/Freenode/daily.sh<br />
<br />
<br />
<h3>
後記</h3>
<div>
inotifywait 可以監看每個檔案修改的動作,產生對應的動作。</div>
Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com0tag:blogger.com,1999:blog-14475696.post-16006432947228853932013-11-28T17:53:00.000+08:002013-11-28T17:54:00.197+08:00Concurrency以前總覺得 <a href="http://en.wikipedia.org/wiki/Concurrency_(computer_science)" target="_blank">concurrency</a> 很難很酷,如 <a href="http://en.wikipedia.org/wiki/POSIX_Threads" target="_blank">pthread</a> 那樣精深,難上手。最近三年的工作經驗認識 <a href="http://en.wikipedia.org/wiki/Asynchronous_I/O" target="_blank">asynchronous I/O</a>,發現這是一種 concurrency,才覺得沒有這麼夢幻,覺得實用。我的工作經驗上,沒遇過 concurrency computing。<br />
<br />
以 <a href="http://en.wikipedia.org/wiki/Memory_hierarchy" target="_blank">Computer Memory Hierarchy</a> 解釋,CPU 以外的 I/O 都是很慢的,讓 CPU 等待是罪過,此決定掌握在 programmer 手上。<br />
<br />
使用 aio 方式我用過幾種:<br />
1) <a href="https://developer.apple.com/library/ios/documentation/general/conceptual/CocoaEncyclopedia/DelegatesandDataSources/DelegatesandDataSources.html" target="_blank">Object-C delegate</a><br />
初體驗,也是啟發的框架。<br />
<br />
2) <a href="http://golang.org/doc/effective_go.html#goroutines" target="_blank">go goroutine + channel</a><br />
新語言的設計。<br />
<br />
3) <a href="http://www.w3schools.com/ajax/ajax_callback.asp" target="_blank">JavaScript ajax + callback</a><br />
常見的方式。<br />
<br />
自從開始有這些體驗,盡量落實每個動作都是 async,朝 C10M 邁進。Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com0tag:blogger.com,1999:blog-14475696.post-72390240816454385512013-10-22T08:59:00.000+08:002013-10-22T08:59:22.314+08:00德國電信商保護境內資料從<a href="http://www.dw.de/us-secretary-of-state-kerry-seeks-to-ease-tension-in-france-over-nsa-spying-claims/a-17174255" target="_blank">美國竊聽流往法國通信被揭露</a>,看到德國的電信商正在<a href="http://www.dw.de/deutsche-telekom-internet-data-made-in-germany-should-stay-in-germany/a-17165891" target="_blank">研擬一個計畫</a>,加強保護境內資料。只要是發送端和接收端都在德國,或是德活盟友。透過路由設定,資料只會在國內走,不會往外。目前看來影響不大,因為太多服務提供者不在德國。<br />
<br />
這個草案表現出一個態度,德國人不喜歡被監聽,可能不選擇美國服務,且自身加強保護。如此一來,德國民眾可能會有更多自己國家的服務,形成特殊現象。Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com0tag:blogger.com,1999:blog-14475696.post-19087363728925092522013-08-08T10:50:00.000+08:002013-08-12T17:40:23.637+08:00使用 rsync & git 建立每日備份工作上遇到災難,救災完畢後評估使用 rsync 和 git 建立每日還原點。<br />
<br />
災難是:<br />
<blockquote class="tr_bq">
前人建立某個帳戶,家目錄在 /,用 <span style="font-family: Courier New, Courier, monospace;">userdel -r</span> 清理舊帳戶,時間過久才發現災難已經造成。</blockquote>
兩個月前閒來無事,有做系統總備份,httpd 和 mysql 是兩個月前的紀錄,客戶難免唉唉叫。救災完畢後,使用 git 建立每日備份。<br />
<br />
主機特性是代管客戶網頁資料,包含圖片和資料庫。<br />
<br />
概略步驟是:<br />
1. rsync 初始,git init<br />
2. 每日 rsync 同步,git commit<br />
3. 每日產生 git bundle<br />
<h2>
Webpages</h2>
<div>
使用 rsync 將來源抓到工作目錄,然後在工作目錄建 git 資料夾。<br />
<br /></div>
<div>
<iframe src="http://pastebin.com/embed_iframe.php?i=A2XH9R73" style="border: none; width: 100%;"></iframe></div>
<div>
<br />
接著每天做備份<br />
<br />
<iframe src="http://pastebin.com/embed_iframe.php?i=qcyrtJVD" style="border: none; width: 100%;"></iframe>
<br />
<br />
最後每天產生 git bundle<br />
<br />
<iframe src="http://pastebin.com/embed_iframe.php?i=qpSeS0XK" style="border: none; width: 100%;"></iframe>
<br />
<h2>
MySQL</h2>
和 webpages 相似的步驟,先初始<br />
<br />
<br />
<iframe src="http://pastebin.com/embed_iframe.php?i=xR6QDste" style="border: none; width: 100%;"></iframe><br />
<br />
接著每天備份,產生 git bundle<br />
<br />
<br />
<iframe src="http://pastebin.com/embed_iframe.php?i=akmgXMpS" style="border: none; width: 100%;"></iframe><br />
<br />
最後產生 git bundles<br />
<br />
<br />
<iframe src="http://pastebin.com/embed_iframe.php?i=vXQLwgmD" style="border: none; width: 100%;"></iframe><br />
<br />
<h2>
還原</h2>
<br />
<iframe src="http://pastebin.com/embed_iframe.php?i=ahJeCHAe" style="border: none; width: 100%;"></iframe><br />
<br />
<h2>
後記</h2>
災難後尋找備份方案時,見到有人每日、每週、每月做不同程度的備份。記得將每日的動作放進 crontab 定時執行,放在離峰時間比較不影響服務品質。<br />
<br />
資料搞失或資料復原都需要付出慘痛的代價,如果能做成自動化,可以降低很多反應時間和損失。</div>
Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com0tag:blogger.com,1999:blog-14475696.post-24019461797232423682013-05-29T15:52:00.001+08:002013-05-29T16:58:45.053+08:00Notification 掉包<a href="http://developer.android.com/google/gcm/index.html" target="_blank">Google Cloud Messaging</a> 和 <a href="https://developer.apple.com/notifications/" target="_blank">Apple Push Notification Service</a> 對於發佈推撥期間裝置離線的處理,都採以下政策:<br />
<div>
<br /></div>
<div>
<blockquote class="tr_bq">
<span style="font-size: large;">只送最後一則。</span></blockquote>
</div>
<div>
<br /></div>
<div>
引用 GCM:</div>
<blockquote class="tr_bq">
GCM will usually deliver messages immediately after they are sent. However, this might not always be possible. For example, the device could be turned off, offline, or otherwise unavailable. In other cases, the sender itself might request that messages not be delivered until the device becomes active by using the delay_while_idleflag. Finally, GCM might intentionally delay messages to prevent an application from consuming excessive resources and negatively impacting battery life.</blockquote>
<blockquote class="tr_bq">
<a href="http://developer.android.com/google/gcm/adv.html#ttl" target="_blank">GCM Advanced Topics, Setting an Expiration Date for a Message</a></blockquote>
<div>
引用 APNS:</div>
<blockquote class="tr_bq">
If APNs attempts to deliver a notification but the device is offline, the notification is stored for a limited period of time, and delivered to the device when it becomes available. </blockquote>
<blockquote class="tr_bq">
Only one recent notification for a particular application is stored. If multiple notifications are sent while the device is offline, each new notification causes the prior notification to be discarded. This behavior of keeping only the newest notification is referred to as coalescing notifications. </blockquote>
<blockquote class="tr_bq">
If the device remains offline for a long time, any notifications that were being stored for it are discarded.</blockquote>
<blockquote class="tr_bq">
<a href="https://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html#//apple_ref/doc/uid/TP40008194-CH100-SW4" target="_blank">Local and Push Notification Programming Guide, Quality of Service</a></blockquote>
<div>
<br /></div>
<div>
所以要自己做驗證,確保推撥有成功。<br />
<br />
比較 <a href="http://line.naver.jp/en/" target="_blank">Naver LINE</a> Android 和 iOS 版本對於離線訊息的處理,一旦接上網路,離線訊息一併收到數則。猜測可能的作法是:<br />
<br />
1. Device offline<br />
2. Send #1 msg, server enqueue 1 msg<br />
3. Send #2 msg, server enqueue 2 msgs<br />
4. Device online<br />
5. Server send queue<br />
6. Device splits msgs and local notificate one-by-one.<br />
<br /></div>
Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com0tag:blogger.com,1999:blog-14475696.post-76982786223507605172013-03-28T08:58:00.000+08:002013-03-28T08:58:11.593+08:00DDoS attacking<a href="http://blog.cloudflare.com/the-ddos-that-almost-broke-the-internet" style="color: #007eda; margin: 0px; padding: 0px;">The DDoS That Almost Broke the Internet</a> 是 CloudFlare 的客戶 spamhaus.org 受到 DDoS 攻擊案例,力道在 90Gbps 到 30Gbps 遊走,持續四個小時,用 anycat 減輕攻擊。<br />
<br />
比較有趣的是下面幾篇文章:<br />
<br />
<br />
<ol>
<li><a href="http://blog.cloudflare.com/deep-inside-a-dns-amplification-ddos-attack" style="color: #007eda; margin: 0px; padding: 0px;">Deep Inside a DNS Amplification DDoS Attack</a></li>
<li><a href="http://blog.cloudflare.com/65gbps-ddos-no-problem" style="color: #007eda; margin: 0px; padding: 0px;">How to Launch a 65Gbps DDoS, and How to Stop One</a></li>
<li><a href="http://howto.wired.com/wiki/Build_your_own_botnet_with_open_source_software" target="_blank">Build your own botnet with open source software</a></li>
</ol>
<br />
Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com0tag:blogger.com,1999:blog-14475696.post-32652880553523162002013-01-09T13:28:00.000+08:002013-10-21T09:09:53.371+08:00MD5 使用注意事項在 Go 裡使用 md5 做校驗不難,如<a href="http://golang.org/pkg/crypto/md5/#example_New">範例</a>所寫:<br />
<br />
<script src="http://pastebin.com/embed_js.php?i=MNpVJMg9"></script>
<br />
若要在迴圈裡做上面的事情,可能會有這樣的寫法:<br />
<br />
<script src="http://pastebin.com/embed_js.php?i=CkQ0q2Pm"></script>
<br />
跑出來的結果是:<br />
<br />
<script src="http://pastebin.com/embed_js.php?i=ZBNHvFx6"></script>
<br />
f1() 和 f2() 會有不同的結果是因為 <a href="http://golang.org/pkg/io/#WriteString">io.WriteString</a> 在 <a href="http://code.google.com/p/go/source/browse/src/pkg/crypto/md5/md5.go">md5.go 實作</a>細節, WriteString 會找 Writer 的實作,而在 md5.go 的實作如下:<br />
<br />
<script src="http://pastebin.com/embed_js.php?i=8igeYSiU"></script>
<br />
看見 += 就可以猜的出來是附加的方式,所以每次非得使用新的 instance,目前還沒發現能清除 digest 內容的方法。Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com1tag:blogger.com,1999:blog-14475696.post-58015680468909386432012-11-08T18:06:00.000+08:002013-10-21T09:08:49.752+08:00Go<div class="separator" style="clear: both; text-align: center;">
<a href="http://golang.org/doc/gopher/frontpage.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://golang.org/doc/gopher/frontpage.png" width="235" /></a></div>
<br />
<br />
這篇記錄最近一個多月學習 Go 的心得。Go 的語法相對於 Object-C 簡潔,後置的資料型態變數宣告,可以懶惰省去資料型態宣告。<br />
<br />
有兩件事情是我碰壁許久:<br />
<br />
<h2>
json.Marshal</h2>
<br />
<script src="http://pastebin.com/embed_js.php?i=Ric72PJs"></script>
<br />
<a href="http://play.golang.org/p/Zg_E_ayyg-">執行</a>結果會得到:<br />
<br />
<br />
<blockquote class="tr_bq">
p1 is: {"FirstName":"John","LastName":"Doe"}.<br />
p2 is: {}.</blockquote>
<br />
<br />
要輸出的成員變數必須大寫開頭才行,下面的 package 方法同樣套用。<br />
<br />
<br />
<h2>
Exported Functions</h2>
<br />
隨意撰碼都需要模組分割,追問題容易,讀碼速度快。Go 使用資料夾結構定義 package 封裝,捨棄 <a href="http://en.wikipedia.org/wiki/Make_(software)">Makefile</a>。<a href="http://golang.org/doc/code.html">How to Write Go Code</a> 闡述如何做到模組化,所有細節皆有提到就是 Function name 首字要大寫沒提到[1],所以一直看到<br />
<br />
<blockquote class="tr_bq">
./main.go:10: cannot refer to unexported name foo.foo1</blockquote>
<br />
程式碼如下:<br />
<br />
foo.go<br />
<script src="http://pastebin.com/embed_js.php?i=LZVHeyUH"></script>
<br />
main.go
<br />
<script src="http://pastebin.com/embed_js.php?i=2aSaQkZf"></script>
<br />
這是最近的心得。<br />
<br />
<br />
Updated:<br />
1. 在 The Go Programming Language Specification 的 <a href="http://golang.org/ref/spec#Exported_identifiers">Exported identifiers</a> 有提到這些細節。Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com0tag:blogger.com,1999:blog-14475696.post-73240820426312822452012-05-09T15:08:00.000+08:002014-04-01T09:35:16.692+08:00Toggle network for iOS SimulatorNetwork fault-tolerant is important to asynchronous request. For iOS simulator can not toggle the network easily, because of its network ability is binding to its level. So that if you turn your host network off, then your iOS simulator network is also down. However, the host lost all network connection.<br />
<br />
The firewall rule can help me do that smart, just block the site and port you would. You can use the below script:<br />
<br />
<iframe src="http://pastebin.com/embed_iframe.php?i=se13DnXx" style="border:none;width:100%; height:80em;"></iframe><br />
<br />
You can change the host you want block in line 3 <span style="font-family: 'Courier New', Courier, monospace;">banHost</span>.Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com0No. 116-118, Dàdūn 20th St, Situn District, Taichung City, Taiwan 40724.1595706 120.652706524.1577596 120.650239 24.1613816 120.65517399999999tag:blogger.com,1999:blog-14475696.post-69262285159078965562012-04-24T18:57:00.000+08:002014-02-08T09:35:08.210+08:00Git hooks Xcode versionXcode has two fields to set version information to app. Version is for releasing number, build is for building number, find more information in <a href="https://developer.apple.com/library/mac/#documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/TP40009249-111349-TPXREF113" target="_blank">Information Property List Key Reference</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoyZyGPQDV_vRuXAooL34drXHdz1QqALyBUTVDzNZG8myasvhvgivrtEc4I9YjzOlPkiWEIcsFJOtERDjmeWbNHiHia2Qbrn1mNlwG3nI2_whZKpMlmABdyNbyuVjYQ2fGHK9k/s1600/Xcode_version_fields.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoyZyGPQDV_vRuXAooL34drXHdz1QqALyBUTVDzNZG8myasvhvgivrtEc4I9YjzOlPkiWEIcsFJOtERDjmeWbNHiHia2Qbrn1mNlwG3nI2_whZKpMlmABdyNbyuVjYQ2fGHK9k/s1600/Xcode_version_fields.png" /></a></div>
<br />
Since Xcode 4.0 starting to support git version control, so that we could bind git tag and commit hash text with Xcode field. The steps in the pseudo-code are below:<br />
<br />
<br />
<ol>
<li>$ git commit -am "COMMIT LOG"</li>
<li>trigger post-commit hooking</li>
<li>Setting the tag number and new commit hash to plist.</li>
</ol>
<br />
<br />
In the real code is like below:<br />
<br />
<iframe src="http://pastebin.com/embed_iframe.php?i=aKXCgw95" style="border: none; width: 100%;height:17em;"></iframe>
<span style="background-color: white; color: #181818; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace, serif; font-size: 12px; line-height: 22px; white-space: pre;"><script src="http://pastebin.com/embed_js.php?i=aKXCgw95">
</script></span>
<span style="background-color: white; color: #181818; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace, serif; font-size: 12px; line-height: 22px; white-space: pre;"><br /></span>
<span style="color: #181818;"><span style="line-height: 22px; white-space: pre;"><span style="font-family: inherit;">Put the code in a file to </span><span style="font-family: 'Courier New', Courier, monospace;">PROJECT_FOLDER/.git/hooks/post-commit</span><span style="font-family: inherit;">, and make it executable.</span></span></span>Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com2No. 116-118, Dàdūn 20th St, Situn District, Taichung City, Taiwan 40724.1593978 120.653024324.1575868 120.6505568 24.1612088 120.6554918tag:blogger.com,1999:blog-14475696.post-79108661548171118742012-04-19T11:05:00.002+08:002012-04-19T11:07:11.023+08:00TEPopUp uses resizableImageWithCapInsets<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcSJB4A6YwlmD1me1wh3mocO6CvwvIfIrxJ2naMclLXP3yxDX_2fF4Lor_7vSadWQ0mHf4aKbCTias_RmRD66AHIXu_RvublrFEvPTIORbKwELu-vDPxFIsj7r01-t_OSWkKQn/s1600/TEPopUp.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcSJB4A6YwlmD1me1wh3mocO6CvwvIfIrxJ2naMclLXP3yxDX_2fF4Lor_7vSadWQ0mHf4aKbCTias_RmRD66AHIXu_RvublrFEvPTIORbKwELu-vDPxFIsj7r01-t_OSWkKQn/s320/TEPopUp.png" width="213" /></a></div>
<br />
<br />
<span style="font-family: Times, 'Times New Roman', serif;"><a href="https://bitbucket.org/a2n/tepopup/" target="_blank">TEPopUp</a> show a pop-up view that stands on a translucent view, it can add something in the dialog view easily.</span><br />
<span style="font-family: Times, 'Times New Roman', serif;"><br /></span><br />
<span style="font-family: Times, 'Times New Roman', serif;">TEPopUp dialog use the api, </span><span style="font-family: 'Courier New', Courier, monospace;">UIImage resizableImageWithCapInsets:</span>, it needs not a full size picture as its background picture, instead of a 28x28 pixel small picture. Obviously, this technical can reduce the who app size. The main core code cuts the area of pattern image, from the center point to right-bottom corner by <span style="font-size: 12pt;"><span style="font-family: 'Courier New', Courier, monospace;">UIEdgeInsetsMake. </span><span style="font-family: Times, 'Times New Roman', serif;">Then, the UIImage returns a new instance thats already expand image to appropriate size.</span></span>Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com0No. 116-118, Dàdūn 20th St, Situn District, Taichung City, Taiwan 40724.1593978 120.653024324.1575868 120.6505568 24.1612088 120.6554918tag:blogger.com,1999:blog-14475696.post-75048772333723675382012-01-10T14:02:00.001+08:002012-01-10T14:02:19.423+08:00UIScrollView 卡關排解因為卡了三次,特別提醒自己。<br />
<br />
若要做成兩頁,則 <span style="font-family: 'Courier New', Courier, monospace;"><b>contentSize</b></span> 要涵蓋兩頁寬度。Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com1Taichung City, Taiwan24.2332076 120.941736823.7698726 120.3100228 24.6965426 121.5734508tag:blogger.com,1999:blog-14475696.post-53597164911648936822011-11-18T16:09:00.001+08:002012-04-19T09:43:34.570+08:00Owned scan screen in ZBarBy studying the ZBar iPhone SDK <a href="http://zbar.sourceforge.net/iphone/sdkdoc/custom.html">document</a>, I need to preview the camera on my own <code>UIView</code>, then, show the scanned image and text, that's all.
All I need is to use <code>ZBarReaderView</code> and <code>ZBarImageScanner</code>, the mainly code snippet as below:
<script src="https://gist.github.com/1375889.js?file=gistfile1.m">
</script>
The screen result like below:
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQmzWxKyMO33zNIfuEc5vKJfNy7gC5b5VQPp8OLvtcyfTAcQsBM6GqcDmQg1FFC-BVe1aHdg4KYNJTrGZ6Zzng0uuGQpeIpbCd58KNYcAjVeCyvj7dh9M8pFle93ye1FlaQsyz/s1600/IMG_0026.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQmzWxKyMO33zNIfuEc5vKJfNy7gC5b5VQPp8OLvtcyfTAcQsBM6GqcDmQg1FFC-BVe1aHdg4KYNJTrGZ6Zzng0uuGQpeIpbCd58KNYcAjVeCyvj7dh9M8pFle93ye1FlaQsyz/s640/IMG_0026.PNG" width="480" /></a></div>
Check out the full sample from <a href="https://github.com/a2n/zbar-iphone-example">github</a>.Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com0tag:blogger.com,1999:blog-14475696.post-45724629108867052302011-11-16T09:38:00.001+08:002011-11-18T11:52:28.215+08:00露天拍賣密碼<a href="https://member.ruten.com.tw/user/editpwd.htm" target="_blank">修改密碼網頁</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizPa-GcWmo_NcV2xvMBwCXdY43Et5CpHmdwc_ER3v1-yHcuJfZl2i4WVCO151ruTxnOC1I-SnJWNFwTIFENvGxPRGpuEZwieM2Ay_ClASvnG_phId4m6KQNCqa8K46OEuTrrrp/s1600/password_length.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="134" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizPa-GcWmo_NcV2xvMBwCXdY43Et5CpHmdwc_ER3v1-yHcuJfZl2i4WVCO151ruTxnOC1I-SnJWNFwTIFENvGxPRGpuEZwieM2Ay_ClASvnG_phId4m6KQNCqa8K46OEuTrrrp/s320/password_length.png" width="320" /></a></div>
希望使用者輸入至多 15 個字元,可是 html 語法卻寫成:<br />
<br />
<br />
<script src="https://gist.github.com/1369025.js?file=gistfile1.html"></script>
<br />
<br />
正確寫法是:<br />
<br />
<span style="font-family: 'Lucida Grande';"><span style="font-size: 11px;"><script src="https://gist.github.com/1369027.js?file=gistfile1.html">
</script></span></span><br />
<br />
另外,<a href="https://member.ruten.com.tw/user/login.htm" target="_blank">登入頁面</a><br />
<span style="font-family: 'Lucida Grande';"><span style="font-size: 11px;"><br /></span></span><br />
<span style="font-family: 'Lucida Grande';"><span style="font-size: 11px;"><script src="https://gist.github.com/1369031.js?file=gistfile1.html">
</script></span></span><br />
<br />
修改密碼規定 15 個字元,這裡卻限制 24 個字元,明顯裡外不一。Alan Lu (盧利雄)http://www.blogger.com/profile/06589021619276060421noreply@blogger.com0