Sunday, August 31, 2014

盤點 Design Patterns

前一陣子有朋友問 Teddy 能否去教他們公司的工程師 design patterns。想起 Design Patterns 這本書  Teddy 已經有一陣子沒有去看它了,最近一次仔細重看書中的 Memento 是為了研究 exception handling 裡面關於 state restoration(狀態回復)的問題,那是多久以前的事現在回想起來居然沒有任何印象...Orz。只依稀記得當年在看 Memento 的時候其實搞不太懂這個 pattern 可以用來幹麼,所以好像從來也沒用過它。一直到 10 幾年後突然發現 Memento 可以應用在例外處理設計,算是替 Memento 找到一份工作了...XD。


Design Patterns 這本書是 Teddy 在 1997年10月24日在天瓏書局買得,算一算已經是14 年前了事了。當初會買這本書,好像是在 BBS 討論區看到某位前輩提到這本書,後來去天瓏翻了一下覺的寫得真棒就買回家。一看之下真的不得了,讀完之後(其實沒有整本全部讀完啦)覺的自己的軟體設計功力大增。書中所講得設計觀念,現在看起來可能覺的是「常識」,可是有好多 patterns 可是 Teddy 自己慢慢在專案中一一自己實做過之後,才體會到這些 patterns 的意義(剛開始自己學習的時候也是一頭霧水)。


***


10 幾年前 Teddy 也有做了一些投影片,在自己還是一知半解的情況下,跟公司的同仁分享 Design Patterns(好東西要跟好朋友分享啊)。當年 Teddy 還是個年輕小伙子,被問到自己也不懂的地方,就說一聲「不會」也就沒事了。但是現在「年事已高」,如果還被問到不會的地方就有點尷尬了(年紀大有年紀大耍無賴的方式...XD)。所以才想說把書拿出來「盤點」一下,看看那些 patterns 是自己很熟的,那些是很少實做而且已經忘得差不多的。
  • Creational patterns:幾乎稍微大一點的案子都會用到裡面的五種 patterns,尤其是 Singleton,Factory Method 和 Builder。
  • Structural patterns:除了 Decorator、Flyweight 以外,其他的 patterns 用到的機會都滿多的。
  • Behavioral patterns:Command、Observer、State、Strategy、Template Method、Visitor 用到的機會最多,Iterator、Mediator 次之,Chain of Responsibility、Interpreter、Memento 比較少用到(後面這三個有用過嗎?)。

對於一個剛接觸 design patterns 的新人,Teddy 會建議學習順序為:

  1. Singleton、Factory Method、Adapter、Composite、Command、Observer
  2. Builder、Abstract Factory、Facade、Proxy、State、Template Method。
  3. Bridge、Strategy、Visitor、Mediator、Iterator、Prototype。
  4. Decorator、Flyweight、Chain of Responsibility、Interpreter、Memento

上述建議純粹為 Teddy 個人的偏見,鄉民隨便看看就好,不用太在意。


寫到這邊突然有一個問題:真的有鄉民把這 降龍18掌 23 個 patterns 一口氣全部都派上用場嗎?有的話請介紹給 Teddy 認識一下,要跟他學習。

http://teddy-chen-tw.blogspot.ca/2012/01/design-patterns.html

Friday, August 29, 2014

MySQL trigger write data to file

Solution 1:

CREATE TRIGGER `insert_cust_fedex_trackernum_lead` AFTER INSERT ON `cust_fedex_trackernum` FOR EACH ROW BEGIN
IF NEW.invoiceNum != '' AND NEW.invoiceNum IS NOT NULL AND NEW.leadTracker = NEW.trackerNum THEN
INSERT INTO cust_fedex_trackernum_lead (idInvoice, idDealer, invoiceNum, trackerNum, created) SELECT tITRec.lId, tITRec.lVenCusId , NEW.invoiceNum, NEW.trackerNum, NOW() FROM tITRec WHERE tITRec.sSource1 = NEW.invoiceNum AND tITRec.nJournal = 8 AND tITRec.bReversed = 0 LIMIT 0, 1;
SELECT NOW() INTO OUTFILE 'd:\\test.txt' LINES TERMINATED BY '\n';
END IF;
END;

Note: If you use INTO DUMPFILE instead of INTO OUTFILE, MySQL writes only one row into the file, without any column or line termination and without performing any escape processing. This is useful if you want to store a BLOB value in a file.

Solution 2:

MySQL UDF (User-defined function)

You can add functions as native (built-in) MySQL functions. Native functions are compiled into the mysqld server and become available on a permanent basis.

http://www.mysqludf.org/

Wednesday, August 27, 2014

How to convert date format in MySQL

SELECT DATE_FORMAT(STR_TO_DATE('08/07/2014', '%m/%d/%Y'), '%Y-%m-%d')

SELECT DATE_FORMAT(STR_TO_DATE('8/7/2014', '%c/%e/%Y'), '%Y-%m-%d')

Saturday, August 23, 2014

1744 追蹤橘報: 切換至简体 程式設計師的時光傳話筒:過去的我,希望你能夠在工作前學會這 9 件事!

(本文為 Medium 駐站作家 Manual Elbert 撰寫,以下以第一人稱敘述)
三年前我在巴塞隆納的神經科學實驗室工作,忙著把電極貼到人身上、教認知系統的課,而現在我靠著設計、編寫軟體維生。
當然從前我在研究科學時就寫過很多軟體。如果你想要看懂 40G 的腦部掃描資料,你必須捲起袖子寫些語法來處理這些數據,而我一直都是個很好的程式編寫者。但直到我辭去了我的學術工作(可能也告別了我的學術生涯)並開始在一個小而有野心的新創公司工作之後,我才真正知道什麼是軟體工程師,以及在這一行是怎麼回事,並不是知道更多程式語法、資料庫、演算法跟設計模型就好。
如果我在讀研究所之前就知道這些事情就好了,將會讓我的工作生涯變得更輕鬆。這是一些對年輕的我的忠告,是我過去三年所學到的經驗,不得不說,有些實在不是那麼美好。
  • 1. 不要高估聰明的價值
年輕的時候,如果你很聰明,你便可以遙遙領先其他人,如同小池塘裡的一隻大魚。如果你那半調子的口才很好的話,那麼聰明的功效還能加倍。事實上,聰明加上口才好能夠讓你不用念什麼書就順利度過高中跟大部份的大學課程。(不過你還是得念物理,你總不能說服一個等式轉彎)。
恭喜你,你很幸運,同時卻也十分不幸運。因為當你毫無阻礙的就衝過了求學的終點線,對待學習如反掌折枝。在這同時別人必須去學習勤勞、堅持、人際網路這些之後遠遠比學識更加重要的東西。
我們的社會太過重視聰明才智了。當我跟人們提到我以前專攻神經科學,大家都會說:「哇,你一定很聰明」。的確我不是笨蛋,但我知道很多人也許不如我這麼聰明,卻是遠比我好的神經科學家。
聰明才智當然還是能幫你打開一扇門,但絕不會幫你做好工作。勤勞、嚴謹、可靠的人際關係都是不只軟體工程師,而是你跨出研究所的美好泡泡之後要成為任何專家都必須擁有的特質。
  • 2. 對你的專業感到驕傲、樂在其中
這句話可能有點老梗,但對年輕的你來說仍然很重要:無論你做的是什麼,都以它為傲,沒有任何事情應該只被視為達成目的的手段。
不論對象是人或是試管,你都必須嚴謹分析你的資料並使你的統計數據有效,然後再重來一遍,因為有時候你會發現你犯了哪些愚蠢錯誤。如果你無法樂在其中,僅把這些步驟視為出版論文或發行產品的必須過程,那麼你永遠無法真正擅長這件事。
如果你是寫軟體的,這代表你要規畫你的特色、研究現有的開源代碼、學習新的模型與程式語言、修復你的錯誤、重建程式碼並且維護它。如果你沒有想要精通你工作的野心,那無論你是科學家、工程是或是任何你在做的工作,可能都只是浪費時間。
你可以擁有一些「寵物計畫」,一些小小的、有點蠢的、並不一定能滿足你的即時目標、你只是因為「享受」在做這件事情。有趣的是,這在軟體社群裡似乎很常見:許多我們現今正在使用的產品大部分都來自某人的寵物計畫,而幾乎不是來自科學圈。我最喜歡的名言之一是來自奧地利動物學家 Konrad Lorenz:
「對一個研究科學家來說,每天早上吃早餐前都拋棄一個寵物假設是好的晨間運動。」
如果你覺得這聽起來很蠢,也許你不該當一個研究科學家。
  • 3. 學習新工具
作為上一點的延伸:投注時間學習新工具。不只是拓展你的抽象知識,而是實際去學那些能幫助你完成事情的工具。這很快就能見效。
一個學習新工具的好方法是上述的「寵物計畫」。每次你要建造新東西時,也用新的方法建造它。記住,寵物計畫就是拿來失敗用的,你投資不多、你學到一點東西;如果計畫不成功,或是你失去興趣、或是你發現實在有點太難了,你不會有損失,不會傷到自己。
如果你從事學術工作,以下是我強力推薦的好東西:
(1) Git 跟 Github
Git 幫助你管理你的工作,再也不用擔心備份問題;而 Github 上有一堆很好用的程式碼,你不需要自己重造輪子。噢,請記得跟你的同伴再確認一次你的程式碼。絕對不要用程式碼來分析那些只有你看過的資料。(我不敢相信我得告訴你這件事情啊,年輕的自己。你一直以來都是一個好的程式編寫者,但我仍然做了那些可能會被忽視的錯誤。如果不是有再檢查一遍,我不會發現因為程式錯誤,有百分之三十的科學結果可能是假的。)
(2) 一個繪圖軟體
我通常都用 Inkscape,但標準的 Adobe Illustrator 跟新的 Sketch其實也一樣好。用這些繪圖軟體來先處理你的圖表和計畫,這通常都比你在 Matlab 或是 matplotlib 上寫繪圖指令來得容易。
(3) 學習如何有效的利用你的文字與代碼編輯器
Sublime Text 是個比 VIM 或 Emacs 來得容易學會的編輯器。知道捷徑能夠幫你省下一堆時間。
(4) 學習如何說話
看看 TED 上的演講並注意這些講者如何在十五分鐘內就抓住觀眾,同時說出那些吸引人的故事。你可以在鏡子前面練習,你的肢體與聲音都是工具。
(5) 知道基本的 Python、R、HTML 跟 Javascript
這些工具可以幫上不少忙。如果你對寫程式並非一竅不通,那學個新的面向編程或資料庫。玩玩計算機視覺、自然語法編寫、網頁擷取、音樂合成跟機器人!
你所能看見解決問題的方法,永遠都會被你所使用的工具所限。學習新工具代表你用新的角度看問題。如果你是大學生,我強力建議你一周之間撥出一天來學習新工具。如果你開始做碩博士研究,那就撥兩天出來。長期來看,你會省下很多時間,而人們會被你的效率所驚艷。如果你覺得這聽起來太困難、你沒有時間、其他壓力太大,那就跟你的老朋友談談,看看到底什麼才是值得你花時間去做的。
  • 4. 成為真正的局內人
正常來說,你的長官或 CEO 會做出對機構或公司最有利益的事情,畢竟那是他的職責。
當我們說到「公司的最大利益」,其實我們是說某些局內人的最大利益。真正的問題是,你的長官或 CEO 到底把誰當局內人?這些利益共享者的利益又有多重要?
如果你的老闆認為他自己是唯一的獲利者(越出名越好、越快獲利越好),你最好快點逃走,逃得越快越好,不然你會被當成犧牲品。那誰才有資格利益共享?你的投資者或贊助者?員工?學生?人類?重點是:快點找出來。如果你不被當成受益者之一,那就快走。無論你有多愛你的工作,那都只是一廂情願、被濫用的關係。
  • 5. 學會展現成果
「Shipping it」變成科技界一個相當流行的詞彙,意即把你的產品從倉庫拿出來給客人。但除了字面上的意思,它其實還有一種精神層面的意涵:你的東西要到了客人手上才會有價值,而這應該是你一直以來的目標。
在學術範疇中,我寫的大部分軟體都只會在一個系統上執行一次。為了產品而寫的程式則是完全不一樣的東西,這會讓五十萬人使用,而當寫程式成為我的專業時,我發現我並不擅長這件事。
但這同時也代表琢磨好幾年,直到完美產品誕生是沒有意義的。你只要做出一點成果,就把它送出去,寫一份最簡單的報告你就有可能被錄取。晚點再擔心更複雜的學問吧,先搞定基礎,盡快發表它。Just ship it。
  • 6. 懂得 80/20 守則
80/20 守則基本上是說,達成你預期目標的 80% 需要花你整個企畫 20% 的時間,而剩下的 80% 時間就是拿來搞定剩下的 20% 目標。這就像你從郊區開車進城市,你用兩成的時間開了八成的距離,但只要你遇到塞車,最後的兩成距離會花你超久的時間。
這重要在哪?因為人們總是低估計畫所需的時間,科學家跟工程師尤其常這樣。這部分要歸因於經驗:你知道得越多,你越能預測之後有什麼會出錯、以及有什麼是人們一開始不會注意到的有趣東西。
如果你還沒有這些經驗,只要把你預期所需的時間乘以五倍,並且預想五倍時間過後你就能達到「快成功了」的階段
  • 7. 你沒出賣你的靈魂
我念博士全都是因為一些錯誤的原因,其中一個我現在稱之為「學術之罪」。我相信如果我沒有追求博士,我就是浪費了我的天份,我覺得我虧欠所以在求學過程中給我幫助的人:教授們、幫我出獎學金的人等等。但我並沒有,他們也許投資了我的學術未來,也或許對他們的投資沒有兌現、沒製造出一個偉大科學家而感到失望,但那是他們的問題,不是我的問題。
這跟做工作是一樣的道理。人們總是會投資你,但那常常是因為這對他們最有利,而不代表他們買走了你的靈魂。
  • 8. 脫離你的舒適圈
以下是我如何看待這個世界的:

如果身邊一切看起來很熟悉,代表你能學的東西極少。但如果你現在處於非常驚慌的狀態,你可能什麼都沒學到。
在舒適圈內,你熟知圈子裡的每個人、那裏是你的歸屬,你知道如何應付問題,太陽底下沒有新鮮事。如果你想學些新知並成長,你必須離開你的舒適圈,那才是學習的開始、有趣的事情發生的地方。那是一個你無法對每件事立即反應過來的地方。
當然也有某些時刻你會被壓垮,那就是驚恐圈,你在那裏昏倒、你所能做的只有勉強維生,並期待某人快來救你。
最棒的地方就正在你的驚恐圈正前面,那裏才有挑戰、你會在那裏學到最多、改變最多。想辦法去到那裏吧。
「忘記安全。在你所畏懼之處住下。摧毀你的名聲。變得惡名昭彰。」-魯米,伊斯蘭神祕主義詩人
  • 9. 學會馴服你的躁動
舒適坐好、閉上眼睛並正常呼吸。專注在你吐出的空氣,通過你的鼻腔撫過你的上唇,沒別的,就專心做這件事。
你剛剛專心了多久?五分鐘?恐怕不到。
一分鐘?很好。
比二十秒更少?恭喜你,你是正常人。你的腦袋就像猴子一樣,會抓住最近的樹枝。在學術上我會換句話說 …… 說好聽一點是「聯想思考」。如果你想要有創意,聯想思考是很好的事情,但它卻是專注力的殺手。
好消息是,你能學會如何專注。外面有一卡車的「提升生產力的技巧」,但他們都只抓到皮毛,你不會想要一個分心自由寫作的軟體,你想要永遠撫平你猴子般跳來跳去的思緒。
對我有效的跟對你有效的可能完全不同。對我來說,定期靜坐冥想非常有效(同時有其他許多優點與副作用),但就算是冥想靜坐也有很多種不同的形態與傳統,而我不可能找到一個對大家來說都適用的。我所建議的,是讓你的意識保持一定的型態,並且很認真的對待它。你認為靜坐是浪費時間嗎?你會去健身房健身,但你應該要兩倍的時間在腦力運動上。
只有好好地集中精神,你才能一步一步完成所有的目標。
(資料來源:Medium;圖片來源:Paul Kline, CC Licensed)

http://techorange.com/2014/08/13/9-things-i-learned-as-a-software-engineer/

Monday, August 18, 2014

7Zip does not terminate exit close after finished completion

Try adding the -y switch (assume Yes on all queries)

Or try to redirect the output content to a file:

cmd /c "C:\\Program Files\\7-Zip\\7z.exe" x Src.7z -oD:\\tmp -r -y > out.txt

Note: sometimes the problems with calling processes is that you need to process / clear the output the produce. once their output buffer is full, they wait for the buffer to come free again.

http://stackoverflow.com/questions/4564367/7zip-does-not-exit-after-processing-large-zip-file-compression

Wednesday, August 13, 2014

C# start run external process program

        private void startSQL(string datadir)
        {
            ProcessStartInfo sqlprocessinfo = new ProcessStartInfo()
            {
                CreateNoWindow = true,
                UseShellExecute = false,
                WindowStyle = ProcessWindowStyle.Hidden,
                FileName = "bin\\mysqld.exe",
                Arguments = "--defaults-file=\"" + datadir + "-my.ini\" --datadir=\"" + datadir + "\""
            };

            try
            {
                Process sqlprocess = Process.Start(sqlprocessinfo);

                if (sqlprocess.HasExited)
                {
                    MessageBox.Show("Start MySQL failed.");
                }
                else
                {

                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                throw;
            }
        }

Tuesday, August 12, 2014

rename move database on MySQL

show tables from old_db;

rename table old_db.tableName1 to new_db.tableName1, old_db.tableName2 to new_db.tableName2, old_db.tableName3 to new_db.tableName3;

SELECT CONCAT('RENAME TABLE ',table_schema,'.',table_name,
' TO ','new_schema.',table_name,';')
FROM information_schema.TABLES
WHERE table_schema LIKE 'old_schema';

Monday, August 11, 2014

Optimize nginx and PHP-FPM (max_children)

As Apache MaxClients, PHP-FPM needs to be optimized to avoid taking your server down.

nginx

Configuring nginx is pretty easy and is described everywhere. For this article, we'll be just focusing on workers.

You should set your worker_process to the number of CPU cores available :

~ # cat /proc/cpuinfo| grep processor
processor : 0
processor : 1
processor : 2
processor : 3
In your nginx.conf file :

worker_processes 4;
You should now edit the worker_connections variable. It's the number of simultaneous requests nginx can handle per worker. So a 1024 value allows me to handle 4096 requests. That should be more than enough. This value mostly depends on your bandwidth capacity and not on your server resources as these requests are extremely lightweight.

PHP-FPM

Here are the three main settings you should know about when configuring your pool (note that I'm using only one pool to handle all sites on the server but you can dispatch resources according to your needs) :

1. pm
The pm variable should be set to dynamic instead of static:

pm = dynamic
By doing so, PHP-FPM processes are started only when needed instead of staying in memory.

2. pm.max_children
pm.max_children is really the most important setting in your configuration. It should be calculated by doing :

pm.max_children = (total RAM - RAM used by other process) / (average amount of RAM used by a PHP process)
For example : My awesome RamNode KVM VPS has 1Gb RAM available and the system and MySQL could use up to 300Mb. I'm hosting Bolt and WordPress sites that consumes around 15Mb during page load. My pm.max_children would be set like this :

(1024 - 300) / (15) ~= 48
3. pm.servers
Other variables should be set to one third of pm.max_children. Like this :

pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 10
The last thing to take into account is the pm.max_requests settings. It's the number of requests a process server can handle before respawing. You should set this value to high values like 200.

pm.max_requests = 200
Don't forget to restart PHP-FPM after you've changed your settings.

Benchmark !

With these settings, I can now launch a basic ab performance test on a WordPress site without any cache enabled :

~ # ab -c 100 -n 3000 http://wordpress.nls.io/
We can observe amazing results :

Concurrency Level: 100
Time taken for tests: 41.534 seconds
Complete requests: 3000
Failed requests: 0
Write errors: 0
Total transferred: 32421000 bytes
HTML transferred: 31668000 bytes
Requests per second: 72.23 [#/sec] (mean)
Time per request: 1384.452 [ms] (mean)
Time per request: 13.845 [ms] (mean, across all concurrent requests)
Transfer rate: 762.30 [Kbytes/sec] received
72.23 requests per second handled by PHP-FPM is pretty good for such a small server. Most of the time needed for the requests is by waiting for a slot to be opened by PHP-FPM because I launched two times more concurrent requests than available PHP-FPM processes. But no errors or timeout were detected.

Have fun with nginx and PHP-FPM !

http://nls.io/optimize-nginx-and-php-fpm-max_children/

Sunday, August 10, 2014

Window Sysinternals has announced a brand new tool Sysmon

Window Sysinternals has announced a brand new tool, Sysmon, a Windows service and driver which logs process creations, network connections, and changes to a file’s creation time.
The service is designed to help users identify malware, but can also be helpful when troubleshooting, or whenever you need to know more about what’s happening on a PC.
Sysmon has no GUI. To install the service, enter  Sysmon -i at an elevated command prompt, or  Sysmon -i -n  to monitor network connections as well (run Sysmon with no switches and it displays all your options).
If everything has worked correctly, the Sysinternals EULA will be displayed. Agree to it, then reboot to run your first test.
Once Windows has started again, launch the Event Viewer (Eventvwr.msc), and browse to the Windows System log on XP, Applications and Services Logs\Microsoft\Windows\Sysmon\Operational for Vista and later.

Sysmon’s recorded events are available from Event Viewer
You should now see multiple events listing Sysmon as a source, along with their date and time, giving you much more detail about what happened during your system boot.
Events with an ID of 1 list a process creation, including the time of launch, Process ID and GUID, file name, command line, user, hash, the parent process and more.
Events with an ID of 2 highlight an attempt to change a file creation date. The report lists the responsible process, the file it’s trying to change, the previous and new dates.
Events with an ID of 3 record network connections, again listing the source process (ID/ GUID/ file name/ user), source and destination IP addresses, host names, ports and port names. (For some reason the host names weren’t resolved in our first test, but this worked properly after we rebooted.)
Basic log management tasks can be carried out with the regular Event Viewer tools. You’re able to filter the log, display just the events you need, search for something important, disable logging when it’s no longer needed, save the events to a file, and more: right-click Sysmon\Operational to see what’s available.
You can also change Sysmon to use its default configuration (no network connection logging) by running  Sysmon -c –  , or uninstall it entirely with  Sysmon -u. The service and driver are removed immediately, and there’s no reboot required.
Sysmon is relatively limited in what it can monitor, but does have several advantages. It survives reboots, is launched very early in the boot process (handy if you’re looking to detect stealthy malware), and is invisible to regular users. Recording its findings as events also ensures you’ve plenty of ways to view and filter them, and overall it looks like another handy Sysinternals tool for power users.

http://www.softwarecrew.com/2014/08/sysinternals-releases-sysmon-1-0/

《電學之父 - 法拉第的故事》讀書心得

《電學之父 - 法拉第的故事》讀書心得

上篇記錄讀後的感受, 這篇純粹記錄讀書心得。

第一章提到法拉第在學徒時期閱讀撒華滋寫的提昇悟性的方法, 對法拉第學習的方式有深遠影響 (p26)。這幾點也讓我獲良多, 重新體視學習方法和其帶來的影響:
  1. 需要做個人手記
  2. 需要持續上課
  3. 要有讀書的伴
  4. 要成立讀書會
  5. 學習仔細的觀察與精確的用字
意即, 要不斷消化吸收知識, 與人討論, 並能簡單易懂地說明給別人聽。如此一來, 才算是習得知識, 提昇自己的思考能力。這都不是短時間能有所成效, 需經年累月不斷練習, 養成習慣, 才會有成效。剛好和我自己的學習經驗有些呼應, 而能體會得較多一些。自己寫筆記、寫給別人看、能因人而異說明清楚, 這三者反映出的理解程度, 有很大一段落差, 可當作另外一篇獨立議題來討論。

在第二章和後面的一些描述, 提到法拉第早年受到別人的輕視, 讓法拉第查覺追求知識的人們, 並不如他原先想像般的也有更高的道德良知, 反而因爭取名利而表現相反的行為。法拉第這麼回顧 (p68):
教育的開始與結束, 都是謙卑。謙卑是深深地感到自己的不足。這種不足感, 不是跟人比較的, 而是我們內心深處真實的貧乏。學的第一步是知道自己的不足。... 所以, 真正的教育在於自我反省, 這種自覺, 就是教育的真諦。
回想中國古人的一些論點, 如《禮記‧學記》提到:
學然後知不足,教然後知困。知不足,然後能自反也;知困,然後能自強也。故曰:教學相長也。《兌命》曰:「學學半。」其此之謂乎?
不論東西方, 追求一些思想到本源後, 似乎會回歸到同樣的觀念。

法拉第查覺受過高等知識 (p177), 不代表有基本的邏輯明辨是非, 讓他很心灰意冷, 而提倡應該將數學和物理納入基本教育裡。
有一位法官攻擊他道: 「科學也不過是一種狹窄的思想, 怎麼能知道靈異世界背後的博大精深? 」 法拉第沒有直接回答他, 法拉第認為這位高級分子的反應, 是高等教育出問題, 以致於不能培養出在基本問題上有分辨能力的知識分子。法拉第回覆道: 「這不是一個高級知識分子所該問的問題, 這提醒了我, 今日許多知識分子已喪失對基本問題的分辨能力, 如同未受教育的人一樣。」
首先我想到莊子說的「曲士不可以語於道者, 束於教也」, 不過我沒有完全理解法拉第的論述, 我有時也會懷疑若科學的基本邏輯有誤 (假設 -> 求證), 是否就無法解釋一些事? 或是我沒有深刻地理解科學精神? 愈深入理解科學, 愈覺得這世上不能用科學解釋的事比能解釋的事多太多了。許多日常生活運作已久的現象, 學得愈深, 發覺愈難仔細地描述內部到底如何運作, 只能模糊猜測概觀。從法拉第的言行舉止可知, 法拉第知道科學的這些限制和人類渺小的知識, 然而, 法拉第選擇從正面用科學的方式探究背後的成因。就像他做了十年實驗仍無法確定電磁的交互作用 (145)。

另外令我好奇的是, 法拉第對上帝有堅定的信仰, 並提到這種信仰和科學精神並無衝突。過去我覺得兩者有所衝突, 還在摸索法拉第的觀點中。科學的精神讓人很難輕易接受任何事物, 相反的, 一但累積足夠證據接受一項事物後, 也不會輕易改變過去的認知。在穩定的知識基石上, 緩慢但確實地朝對的方向往上前進。

http://fcamel-daily.blogspot.ca/2011/04/blog-post_10.html

《電學之父 - 法拉第的故事》讀後感

《電學之父 - 法拉第的故事》讀後感

偶然的機會下, 看到別人推薦這本, 順手買來讀讀。沒想到, 光是翻閱前言就覺得這本書相當有趣。為了能慢慢享受閱讀本書的樂趣, 我沒急著一口氣讀完, 而是偶而讀個一小段, 分成多天讀完。

了解法拉第純樸到不知變通的個性, 以及對待科學的真誠, 又燃起我心中微弱的火種。在第十一章裡 (p109), 法拉第遭到學界的人中傷, 他妻子撒拉這麼對他說:
我寧願你像一個孩子, 因單純而受到傷害; 也不要像一個小人, 因受傷害而處處對人提防。
讓我想到, 在過去不長的人生歲月裡, 偶而會因一些堅持而很感到很累, 幸好有剛好看到母親的言行, 重新拾起我認為「正確的事」。現在看到法拉第的情況, 更有感觸。

書中提及法拉第為科學樂此不彼的一生, 拒絕接受名利來衡量他在科學的發現, 而以在研究科學中已獲得大大的喜悅, 不斷地回絕各種職務邀約和酬勞。讓我多少能明白, 為何有些數學家、科學家, 會不願接受獎項。那種為科學發現而喜悅, 深怕單純之心被摻雜其它情緒的思維, 不是身處在名利世界的我們所能體會的, 反而會用「只是想拒絕獲獎來提昇名氣」這種說詞看待他們。

法拉第的戀愛觀和他妻子默默的支持也令人為之動容, 在為他笨拙的表現大笑之餘, 也深深感到認同。像是他對妻子描述的這段話 (p95):

我是一個糊塗的人,因為我的頭腦掛念太多東西,
甚至當我在想念妳的時候,我仍想到
氯氣、油燈、合金、水銀、戴維、五十個煉爐,還有許多實驗細節,
因此我常落入一種心不在焉的窘境。
昨夜,我在書中發現皇家學院的鑰匙夾在書中,
我急忙送回,免得明天學院無法開門,
我的思想雖然常有紛擾,但是我知我心鑰匙的所在,
希望妳幫助我,看顧我心的鑰匙。

在書本的末頁, 讀著附錄的年表。從頭檢視法拉第的一生, 讀到「一八六七年 逝世」這行, 我不禁鼻頭一酸, 為這位謙遜的大科學家回歸天國感到不捨。
http://fcamel-daily.blogspot.ca/2011/04/1.html

Saturday, August 9, 2014

追求神乎其技的程式設計之道(番外篇)

我的學習過程

還記得小時候我和我弟上過一個奇特的數學補習班,叫做「功文數學」。他們的「教學」方法非常特別,不像一般的教室會有一個老師在講台上教課,而是每個人會拿到一疊數學題目,每一面都有數個計算問題,像是「10 x 2 = ?」這樣的問題。每次去功文的任務就是把那一疊題目寫完,寫得越快的人就可以越早回家。那些題目說來沒什麼意思,從頭到尾全都是計算問題,難度從最基本的加減乘除,一直到微積分都有。每次寫完題目後,會有個類似老師的角色,拿出解答本幫你對答案,打上成績。如果在那老師能應付的範圍內,他可能還會跟你說說哪裡犯錯了,下次多加油之類的,但如果到了國高中程度的問題時,老師的作用就只剩對答案而已了。
我之所以說這個補習班很奇妙,原因就在於這個教學過程中,講求的是大量的計算和自我學習的能力。我從加減乘除開始,一路這樣寫到了微積分,寫到後來那邊的老師也沒辦法批改了,乾脆把解答本拿給我們看,讓我們自己看解答學。起初我還覺得這個補習班挺不錯的,只要我做得越快就能越早回家,對小孩子來說是個很好的誘因。而且因為大量的訓練,讓我的計算能力變得非常好,國小國中時的數學考試我都不用準備也能很快寫完交卷。但後來我開始覺得不太對勁,很多題目我雖然知道怎麼算,但我其實不懂為什麼要這麼算,或是這麼算的意義是什麼。可是台灣的考試也不管這個,反正你只要能得到答案,根本沒人在意過程是怎樣。
功文數學的這套方法對訓練計算能力而言很有幫助,因為計算就是需要大量的練習才能變快變好。但問題是,計算能力再好,也是只能算已經定義清楚的問題(也就是考卷上的問題),而無法發現新問題並定義問題,更糟的是還會讓人習慣在沒有完全理解背後的概念時只學得方法快速得到答案。
在我高中開始參加程式比賽後,我用了我熟悉的這套方法訓練自己的程式能力,自己一個人大量的找題目練習。每天從早練到晚,即使沒有人教我也覺得很正常,因為我從小就是這樣自學起來的。這樣練了一年後,我能飛快的寫程式和解題,看到熟悉的題型就能馬上開始敲鍵盤,但同時我也開始覺得寫程式變成一種機械化的過程:看題,解題,寫程式,看題,解題,寫程式…。跟我從小做數學似乎沒兩樣。
我開始覺得無趣。即使我程式寫得再快再好,也只是解出一個別人設計好的問題而已。
心中的聲音不斷的說:「為什麼我要做別人早就知道答案的問題?
我想要做沒有人做過的事,看到沒有人看到的問題,再親手解決這些問題。
當我開始這麼想的時候,我正在一邊學著做科展。科展全名是科學展覽,意味著要做點跟科學有關的事來展覽。以前的文章提過,我高三時夢想著要讓電腦自己寫程式,我覺得這是一件沒人做過的事,非常酷,所以我就一直專注在這件事上(其實當時就有很多人在做這種研究了,只是我不知道而已)。但從一開始到我被選上去美國參加國際科展時,我都一直不覺得這件事科學在哪,頂多說是一個工程(或工藝)作品。但選上代表後是有些好處的,台大的歐陽明教授給了我一些指引,讓我知道「科學方法」得測量和量化這個作品的結果,才有客觀的數據可以知道它的作用,進而跟其他相似作品比較好壞,也因此我才開始對「做研究」這件事有點概念。(到這時我才想起來,小時候雖然有做一些物理化學實驗,但從沒人跟我說過這些實驗是有一套標準的方法和流程的,當然也沒人跟我說這件事的價值所在。)
雖然做科展挺有趣的,但同時我也對科學感到失望 – 因為我意識到科學方法沒辦法幫助我們發明新東西,只能用來評估和檢驗已知事物的好壞。至於所謂的創新科學研究,也是得先提出一個假設(hypothesis),然後再用這套標準方法去驗證它是否成立。但到底要假設什麼事情呢?科學可沒辦法告訴你。
上大學後,我看到當時處在黃金時代的MIT Media Lab所產出的許多創新研究成果,也開始接觸到設計(design)這個領域。我發現Media Lab的人大多有跨領域的背景,像是設計師+電機工程師、或是音樂家+軟體工程師,他們常看到別人看不到的問題,並提出簡單又優雅的解決方法。我以前一直以為做設計的人講求的是美術天份,但後來深入了解後才發現這是個大誤會。設計的目的是解決問題,跟程式設計師其實沒兩樣,只是用的工具是紙筆或模型罷了。(但一個好的設計通常也都很「美」就是了)
雖然如此,設計師和工程師也有很大的不同。設計師對四周環境和日常生活很敏感,常常得在生活中注意各種細節的不完美之處。但工程師成天泡在電腦中,而且很善於使用其實很難用的介面和程式(像Linux、vi、command line、還有各種程式語言),甚至引以為傲,日子久了也就不覺得這些東西有什麼問題。泡在程式碼中的工程師也一樣,如果習慣了和前人或其他人的大便碼相處,久了也就不覺得臭了。
發現這些現象後,我開始學著跳脫出原本習慣的一切,開始注意生活周遭的各種細節,思考為什麼這個東西當初要這樣設計、這樣做有什麼好處和壞處、有沒有更好的方式之類的問題。之後,當我習慣觀察細節後,慢慢察覺到我習慣用的軟體、工具、環境、程式語言,處處都是設計後的結果,而且充滿可以改進和創新的空間。這些東西都不是沒來由的產物,而是經過某些人思考過後的結果,甚至是經過好幾輪的演化結果。可惜平常在學習或教學的時候,很少人會提到這些歷史淵源和演化過程,以至於這些設計都變成理所當然的存在。但如果我們能仔細觀察平常的事物,進一步思考就會發現很多設計都是為了因應當初時空環境的限制,而這些限制現在不一定存在了,所以我們就會有發揮的空間。
眼光拉遠後,能看到的問題更多了。到了這個階段,能力強的人會覺得能解決的問題也很多。但上天給每個人的時間是一樣多的,這時重要的事情反而又變成:「找出最重要、最根本的問題來解決,而不要被眾多的小問題和小機會所分心,才能產生最大的影響力」。
回顧我的學習過程,我會覺得每一個階段都是一塊基石,一塊塊往上疊以後才會具備該有的能力和經驗做下一階段的事情。舉例來說,要是我一開始沒投入程式比賽的練習累積足夠的實作能力,之後我就沒辦法隨心所欲的寫出我想寫的程式,也沒辦法參加科展體會做沒人做過的事有多麼有趣。之後我可能就會一昧沉浸在鑽研各種流行技術中,或是眼高手低說得一嘴好主意但卻做不出什麼來。
雖然學習是一步一步往上走的,但過程中每件事都有反面的效應,讓我不知道是不是做別的選擇會更好。像是我覺得功文數學浪費了我太多時間在數學計算上,而限制了我在其他方面的發展,但同時它也讓我養成靠自己學習的習慣;參加程式競賽也有類似的效應,雖然增強了我的程式能力,但也讓我錯過正常的高中生活和課程(雖然說到目前為止沒有覺得有什麼負面影響)。
無論如何,我相信在成長的過程中適當的大量練習是必要的。異數(Outliers: The Story of Success)一書的作者Gladwell說要精通一件事情至少需要一萬小時的練習,我相信這是真的。我在高中為了比賽所做的練習起碼就超過五千小時,上大學後輕易就超過一萬小時,但其實我也不覺得我真的精通了什麼。經過大量的練習,本來很難的技巧或技術都會變成一種本能,可以很自然的使用它來從事更高階的應用或是建構更複雜的技術。沒有這些基礎,也就很難站在更高的地方看得更遠想得更多,我也不會走在現在的道路上。

http://blog.vgod.tw/2011/02/23/divine-code-extra/

追求神乎其技的程式設計之道(十)

很多人都聽說過,同樣是寫程式,一個頂尖程式設計師和一個普通程式設計師之間的生產力可以有十倍甚至百倍的差距。這是其他行業很少見到的現象,於是不禁令人納悶,為什麼會這樣呢?
其實單就解決同一個問題的coding能力來說,差別還不至於這麼巨大。我在高中參加奧林匹亞和大學參加ACM比賽時,已經遇過全世界數一數二的coding高手,這些人每天都在練習解題和實做各種複雜的演演算法和資料結構,隨便說一個演演算法都能直接把code透過肌肉記憶反射出來給你。他們能在數十分鐘內想出高效率的演演算法並寫成程式解決一個複雜的難題,即使我高中時已經花了一整年在訓練,依然不是他們的對手。這些人除了絕頂聰明外,每個人在高中時少說也寫過至少十萬行的code。但我發現,即使他們能解一般人解不出來的問題,打字快到鍵盤會冒煙,在做一個大系統時,這方面的差距還不一定會如此明顯。
所以我想,除了先天的智商和後天對於寫程式的熟悉度與經驗外,一定還有什麼因素造成巨大的生產力差異。
我後來發現,程式設計師和其他行業有個很大的不同點:一般行業只能在現有的工具上磨練自身的技術,但程式設計師除了磨練技術外,還可以獨自創造、修改自己使用的工具;換句話說,程式設計師的能力就是在電腦上創作出更好的軟體,不但能便利他人,也同時能增進自身使用電腦的工作效率。舉例來說,理髮師能磨練使用剪刀和設計髮型的技術,但理髮師並不知道怎麼發明及製造新的剪刀讓自己更有效率的剪頭髮;電機、化工、土木工程師要設計IC、化學製程、建築結構,但他們得依賴電腦軟體才能設計,並且靠許多大型機器和工具才能生產,即使想提昇自身的工作效率,也不是自己一個人想做就能辦到的。但軟體工程師就不同了,我們只靠一台電腦就能工作,我們的工具是軟體,我們的產出也是軟體,我們的所依賴的一切都是軟體,只要自己願意投入心力,隨時可以修改每天使用的工具和系統讓自己更有效率的工作。
這一點可以說是程式設計師的先天優勢,也是頂尖的程式設計師和普通程式設計師的生產力差距的關鍵。

Eat Our Own Dog Food

我發現厲害的程式設計師常有種共同特質:寫工具給自己用,解決自己日常工作碰到的問題或改善自己的工作效率。英文有句話叫eat one’s own dog food,字面上意思是說一家公司應該要吃自己做出來的狗食,實際上是引申為一家公司應該要在內部用自己的產品解決自身的問題,才能發現真正的問題,並且說服人這東西真的很實用。Google是奉行「吃狗食」原則的典型公司,Google內部有一個獨立的搜尋引擎搜尋公司內部網路的資料,新技術也都能在上面先行測試;Google內有獨立的gmail、google docs,都在對外公開前先讓內部的人實際用上好一陣子;Google甚至做了自己的Linux distribution給工程師用、自己的compiler、自己的瀏覽器…。
會這樣做的動機其實很簡單:如果我每天都要花10分鐘手動做同樣的事情無數次,為什麼不花一個小時寫個程式把這件事情自動化,以後可以省下更多時間做點真正有意義的事;如果我每天都要用這個彆腳的軟體,忍受他設計上的不便,為什麼不想法辦改善它或自己做一個呢?
程式設計師每天都用電腦在工作,尤其做一個系統時常常需要花時間做一些瑣碎的工作,像是編輯設定檔、把一些檔案搬來搬去、重開伺服器、清除暫存檔…等等。這些工作通常不難,但可能步驟繁雜,或是每個步驟都要等待它慢慢完成,累積起來每天就很容易浪費許多時間手動做這些無趣的事情上。
出於「懶惰」的美德,頂尖的程式設計師工作時想的不只有產出最終產品就好,而是如何花最少力氣最少時間把產品做到最好。但這件事說來容易做來難,能不能實行往往跟程式設計師工作的系統環境有很大關係。

UNIX是Programmer的天堂

如果要說我高中時期最大的收穫是什麼,我想有兩件事的重要程度不相上下:一是我確認了自己對寫程式的熱情,並且花了足夠多時間打好基礎;二是我在這段時間內摸熟了Linux,並且愛上了UNIX世界工作的哲學。
UNIX可以說是一個非常適合程式設計師工作的天堂,UNIX的工作哲學(泛指所有UNIX like的系統,像是Linux、BSD、Mac OS X..等等)是提供許多小工具,每樣小工具只做一件事,使用者可以合併使用多種工具完成複雜的工作。此外,UNIX的工具都是以command line為介面,非常適合寫script做自動化的操作。而在Windows的世界中則完全不同,Windows上的軟體傾向於提供整合式的GUI環境,把所有相關或可能會用到的功能全都一手包下,雖然方便使用者,可以點幾個按鈕就自動做完所有事情,但對於程式設計師來說其實不是一件好事。
以寫程式的工具來說,在UNIX下可以選自己喜歡的文字編輯器,不管是Vim或Emacs,也可以選自己喜歡的compiler,可以用makefile加上command line工具自動化整個程式編譯、測試、執行的流程,並且隨時都可以加入shell script或是perl script把開發流程中瑣碎的工作一併自動處理,不管需求有多麼特別,這種完全自訂的流程彈性可以說是無限大。
但在Windows環境,主流開發軟體以整合開發環境(IDE)為主,像Visual studio這種無所不包的巨獸,對於新手來說按一個鍵就能搞定一切,不用去想底下的細節,實在方便得很。可是依賴於IDE卻有個致命缺點:只要是IDE的設計者一開始沒考慮到的事,你就沒辦法做。
舉例來說,早期visual studio不支援版本控制系統(version control system)時,程式設計師就很難把版本控制整合到開發過程中(例如說在編譯成功時自動commit、或是自動加入新的原始碼…);即使到現在visual studio已經支援了一些常見的版本控制系統,用它的人依然要看這個支援的清單包含哪些系統,如果是想用新的系統,或是用非標準的方法使用這些系統,恐怕只能遺憾的兩手一攤什麼事也不能做。有些IDE雖然有提供plugin功能(像是Eclipse),但其實也沒好到哪,因為IDE龐大無比,寫plugin的難度和所需時間遠高於使用者手動完成這些日常瑣事所花的力氣,自然不會有多少人願意去做。
簡單來說,用IDE的話,程式設計師沒辦法掌控自己用的工具,也沒辦法改善開發流程中的問題,開發效率的極限很自然會被IDE限制住。但UNIX上的環境就不一樣了,採用多種工具的組合讓自己能掌控開發流程中每個步驟。因為每個步驟和所用的工具都是透明的,只要有需求或是發現哪裡可以改善,很容易可以從滿手的工具中抓出一個來解決,或是寫個迷你的script來自動處理較複雜的工作。即使哪天有新的小工具出現(例如說一個新的版本控制系統),因為每個小工具都是獨立運作,靠程式設計師自行整合的,所以也比較容易把舊的「零件」替換掉。除此之外,open source興起後,帶有原始碼的系統更帶給程式設計師一個「完全控制」的機會,除了能替換零件外,有能力的人還能直接對零件本身做修改以符合自己的需求。種種因素加起來,讓程式設計師不再被單一個工具能力所限制,而是手中握有無數可以自由運用的籌碼,唯一的限制只有自身的創意和熱情而已。

狗食是生產力的關鍵

我一直覺得念資訊系的人不應該依賴於用IDE寫程式,當然這並不只是因為「用command line才是真男人」這種geeky的理念,而是念資訊系的應該要能擅長於「把電腦能做的事交給電腦做」。今日的軟體介面大多是以多數的日常使用者為目標,雖然方便操作,但設計者不可能把所有使用者可能會想做的工作列表做出各種排列組合放在選單裡。如果是設計者沒考慮到的功能,使用者往往也只能手動慢慢處理。但程式設計師和一般使用者是不同的,程式設計師的能力就是和電腦溝通,讓電腦用我們想要的方式幫我們完成工作。如果我每天要重複按照順序按100個不同的按鈕,為什麼不寫個程式自動按這100個按鈕?
我跟一些人聊過這個想法,但典型的反應是「正事都做不完了,哪裡有時間先做一個工具?」
但我覺得很諷刺的是,正是因為抱持這種觀念才會讓生產力低落,所以讓正事做不完,時間越緊迫就越不敢花時間做這種沒有立即產出的事情。相反地,如果在意識到自己已經三番兩次手動重複執行同樣的冗長工作時,就應該靜下來好好想想是不是有什麼辦法可以讓電腦來做這些事,只要常有這種想法,寫這些script和小工具所節省下來的時間和自己得到的經驗是一輩子都用得上的。
現在有許多open source軟體一開始都只是程式設計師為了方便自己所寫的小工具,在做正事的時候撥出時間先做好工具,然後不知不覺可能就成了偉大的軟體。最有名的例子是Knuth為了寫他的The Art Of Computer Programming,他竟然先重頭自己打造一個針對數學環境設計的排版系統,最後就成了著名的TeX。他不但完成了電腦科學界的聖經,還「順便」完成了一個經典的排版系統並分享給全世界使用。
如果持續抱持著這種態度寫程式,說不定你我也能成為下一個Knuth呢? (笑)
(待續)

http://blog.vgod.tw/2009/12/18/divine-code-10/?relatedposts_exclude=857&variant=zh-tw

向上管理:從定位你與主管之間的真正關係開始

走在辦公室的路上,遇到了一位許久沒見的朋友,他說:「這禮拜是我最後在這邊的一個禮拜?」「嗯?你要離職了?」我問。他說「對啊!有點難適應,我沒辦法適應這邊的文化」,我們握握手祝福了一下,彼此就先告別了。
我心中想起了四個字「向上管理」,這是我對他最深刻的印象,因為三個月前我就常從他的口中聽到這四個字,名校的博士、RD能力很好的員工,但卻無法適應。
通常從嘴中講出這四個字的朋友,幾年後我都沒有看到他們有多好的表現,但是那些能力優良的員工,被他們眼中不那麼適任的主管幾句話或是幾個 KPI 就問到啞口無言的,我倒是看過不少。我想這也該是時候去思考所謂的「向上管理」的定義是什麼?是誤用?還是迷思?
多年職場觀察的真實定義
我想跳脫在網路上可以查到的那些定義,與你們分享我在職場上真實的觀察到的定義:
向上管理,是主動積極的付出,而不是真的要去管理主管,更務實的說,你只是積極的管理你的任務。
這讓我想到之前認識的另一位朋友,他能力普普、沒有多大的關鍵研發成果,卻是他們部門主管眼中的良將,與他相識多年,我想他才是那位口中從未說出「向上管理」,但卻踏踏實實踐這四個字的人。我從他身上觀察到了三個關鍵原則:堅持積極、堅持小事、堅持溝通。
但是在說這三個原則之前,有個概念需要先被瞭解,你眼前所見到的主管(要是你不是那麼認同的),你要知道一件事,這些主管都不是他們原來的樣子。
開不完的會、對上的提案、對下的溝通與瞭解,看似需要又不重要的應酬和那些業績壓力下的權宜之計。這些主管大概都只能付出他能力的四成到五成(半殘)去處理正事,也就是說他們是需要幫助的一群人,而誰可以讓分擔他的包袱,誰就是懂向上管理這四個字的人。你曾經用這樣的角度去看待你主管與你自己的定位嗎?
原則一:積極 vs 堅持積極
積極是一個態度,但是態度很容易受到環境的改變,尤其遇到不認同的主管與企業環境時,這樣的態度會消失的很快,但是「堅持積極」是一種競爭力。」

堅持積極的關鍵其實就是你的看待主管的態度「他應該是我要幫助與服務的對象」時,你的積極就不容易受到環境與文化的影響,因為你認清一件事情:他就是需要幫助!因為你知道你被指派的任務雖然完成了,但卻不一定可以達到計畫/專案任務的策略目標,大多數的員工則是以完成任務作為任務的句點,卻沒有多去思考這手上的任務是否達成了當初主管腦中那需要被達成的目標。
Tips: 如何察覺主管目標?先仔細的詢問自己「為什麼」,為什麼要作目前的任務?要是想不出來?或是想過之後在與主管確認他的布局與策略。
原則二:堅持小事(團隊溝通)
在印象中,那些我覺得配得上「向上管理」的員工,他們大都是多位共事主管信任的對象。
他們除了處理他們職務上的任務之外,我更觀察到他們會主動的找尋那些未被人撿起但卻需要被處理的事情去發揮,在大部分的時間裡這些事情大多都是事前溝通、團隊向心力與時程管理等事項。有時候讓團隊整體往前的關鍵,就是由很多這樣的小事所建構起來。

不論大事或是小事他們都有一個恆久不變的特質,那就是「都需要有人去處理」,事情再小,沒處理都會變成最後壓垮人,或是大大的降低專案品質的原因。所以為什麼你會發現,在不同的公司中都會有一到兩個主管所愛用的員工,原因無它,他們主動積極的去發現主管的需求,像是需要有人跟催,需要有人主動進行跨團隊溝通,人與人之間的競爭優勢就在那邊,而他們自己走過去爭取。有時候不要忌妒那些做些小事情而得寵的人,因為在這方面你 do nothing。
Tips: 當你聽到你的團隊成員在抱怨的時候,你除了不要加油添醋之外,你有思考過如何可以讓他們不抱怨嗎?遇到沒人處理的事情時,你會主動處理嗎?處理後你有定期的回報主管嗎?
原則三:堅持溝通
管理,是為了讓任務如預如質的執行與整合。
當今天你收到一個任務時,你有沒對這任務做一個基本的盤點呢?其實不論向上或是向下管理,甚至向左向右,在要完成一件任務時的基本資訊是不會變的,人就是無法在黑暗中雕出一做沙堡,要完成一件任務就是該有基本的資訊:「何時要?要做到什麼程度?有無資源(預算、人力、技術)?」這些都是主管可能在交代任務時會忘記的資訊,你有沒有在第一時間掌握?若是缺了這些資訊,你是否可以主動的提問?
溝通永遠都是在事情發生意外之前才有意義,事後的溝通其實都叫藉口。
你有無聽到自己心中那個微小的聲音「好像少了什麼」然後主動的跟主管確認?其實這就是溝通的關鍵,你意識到了你缺乏完成任務的資訊或是資源,而不是接到任務後就低頭努力,到最後才發現有太多的「早知道我就…」的遺憾。
Tips: 給自己一張列表,上面就寫著你覺得你需要完成一件任務時的欄位,利用表格管理,管理自己每一次的任務資訊與資源是否充足。而也只有這樣你才會很清楚的意識到你其實需要堅持溝通。

與主管站在同一邊
當你積極的瞭解主管的苦處與目的時,你其實已經是站到主管的同一邊去一同面對與體諒他的問題與壓力,適時的擔任起哪些沒人處理的小事情(團隊溝通),並在一開始就去思考要完成每件任務的資訊與資源是否充足,並主動做出反應與付出,讓你的主管隨時可以掌握任務執行的情況。告訴我,假設你有這樣的部屬你會怎麼看待他?
向上管理,說穿了就是主動積極的付出所延伸出來的行為,而不是真的想要去管理,別傻了,不是嗎?

http://www.managertoday.com.tw/?p=42262

Wednesday, August 6, 2014

find command two multiple file extensions with regular expression

# find . -type f -name '*.module' -o -name '*.js' | xargs -I {} grep -riH 'find_string' {}
# find -E . -type f -regex '.*\.(module|js)' | xargs -I {} grep -riH 'find_string' {}

Note: That -E flag is a BSDism (OS X having a largely BSD-ish userland). On GNU find, you instead say -regextype posix-extended, as an expression rather than a flag (according to Dennis Williamson's comment, which is doubtless correct).

Friday, August 1, 2014

rsync - synchronizing two file trees strcuture

rsync - synchronizing two file trees strcuture

rsync is an amazing and powerful tool for moving files around. I know of people that use it for file transfers, keeping dns server records up-to-date, and along with sshd to remote restart the services when rsync reports a file change (how they do that, I don't know, I'm just told they do it).

This article describes how you can use rsync to synchronize file trees. In this case, I'm using two websites to make sure one is a backup of the other. As an example, I'll be making sure that one box contains the same files as the other box in case I need to put the backup box into production, should a failure occur.
Overview

rsync can be used in six different ways, as documented in man rsync:

1. for copying local files. This is invoked when neither source nor destination path contains a : separator
2. for copying from the local machine to a remote machine using a remote shell program as the transport (such as rsh or ssh). This is invoked when the destination path contains a single : separator.
3. for copying from a remote machine to the local machine using a remote shell program. This is invoked when the source contains a : separator.
4. for copying from a remote rsync server to the local machine. This is invoked when the source path contains a :: separator or a rsync:// URL.
5. for copying from the local machine to a remote rsync server. This is invoked when the destination path contains a :: separator.
6. for listing files on a remote machine. This is done the same way as rsync transfers except that you leave off the local destination.

I'll only be looking at copying from a remote rsync server (4) to a local machine and when using a remote shell program (2).

Installing

This was an easy port to install (aren't they all, for the most part?). Remember, I have the entire ports tree, so I did this:

# cd /usr/ports/net/rsync
# make config-recursive
# make install clean distclean
===> The following configuration options are available for rsync-3.0.9:
     POPT_PORT=off "Use popt from devel/popt instead of bundled one"
     SSH=on "Use SSH instead of RSH"
     FLAGS=off "File system flags support patch, adds --fileflags"
     ATIMES=off "Preserve access times, adds --atimes"
     ACL=off "Add backward-compatibility for the --acls option"
     ICONV=on "Add iconv support"
     TIMELIMIT=on "Time limit patch"
===> Use 'make config' to modify these settings
If you don't have the ports tree installed, you have a bit more work to do.... As far as I know, you need rsync installed on both client and server, although you do not need to be running rsyncd unless you are connecting via method 4.

Setting up the server

Edit /etc/rc.conf
# vi /etc/rc.conf
### enable rsyncd, using IPv4 instead of the default IPv6.
rsyncd_enable="YES"
rsyncd_flags="-4"

You might run rsyncd manually. If your server only uses IPv4, then, make sure you add the "-4" argument to the command
# vi /usr/local/etc/rc.d/rsyncd

Change:
command_args="--daemon"

To:
command_args="-4 --daemon"

Edit /usr/local/etc/rsyncd.conf

In this example, we're going to be using a remote rsync server (4). On the production web server, I created the /usr/local/etc/rsyncd.conf file. The contents is based on man rsyncd.conf.

# vi /usr/local/etc/rsyncd.conf
address = 192.168.100.78

charset = utf-8

uid = www
gid = www

use chroot = no

max connections = 20

syslog facility = local5

log file = /var/log/rsyncd.log

#pid file=/var/run/rsyncd.pid
#lock file=/var/run/rsyncd.lock

max verbosity = 2

transfer logging = yes

[web]
hosts deny = 0.0.0.0/0.0.0.0
hosts allow = 192.168.1.2, 192.168.1.3

auth users = rsync_bot1, rsync_bot2
secrets file = /usr/local/etc/rsyncd.secrets

path = /www/rsync_tmp
comment = whoe www (approx 10gb)

read only = no

[home_ftp]
uid = root
gid = ftp
hosts deny = 0.0.0.0/0.0.0.0
hosts allow = 192.168.1.2

path = /home/ftp
comment = ftp files

auth users = home_ftp_user0
secrets file = /usr/local/etc/rsyncd.secrets

read only = no

Note: you can choose to put setting on global level or module (section) level.

Adding any local-net entries to your /etc/hosts file so that rsync's name lookup uses that information.
# vi /etc/hosts
192.168.1.2 test2
192.168.1.3 test3

Creating Log file
# touch /var/log/rsyncd.log

automatically rotate logs
# vi /etc/newsyslog.conf
### rsync
/var/log/rsyncd.log 600 9 100000 * Z

Create the Secret File
# touch /usr/local/etc/rsyncd.secrets

# vi /usr/local/etc/rsyncd.secrets
rsync_bot1:mypass
rsync_bot2:mypass
home_ftp_user0:mypass

Make /usr/local/etc/rsyncd.conf non-world readable:
# chmod 440 /usr/local/etc/rsyncd.secrets
# chown root:wheel /usr/local/etc/rsyncd.secrets

You'll note that I'm running rsync as www:www (or rsync:rsync depends on your situation).

# cat /etc/master.passwd | grep www
www:*:80:80::0:0:World Wide Web Owner:/nonexistent:/usr/sbin/nologin

# cat /etc/group | grep www
www:*:80:

Then I started the rsync daemon and verified it was running by doing this:
# /usr/local/etc/rc.d/rsyncd start

Monitor rsync log file
# tail -F /var/log/rsyncd.log
rsyncd version 3.0.6 starting, listening on port 873

# ps auxww | grep rsync
root 737 0.0 0.1 3128 1348 ?? Is 10:50AM 0:00.00 /usr/local/bin/rsync -4 --daemon

# sockstat | grep rsync
root rsync 1763 4 tcp4 *:873 *:*

Then I verified that I could connect to the daemon by doing this:

# telnet localhost 873
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
@RSYNCD: 21

I determined the port 873 by looking at man rsyncd.conf.

Open rsync port in firewall.
# vi /usr/local/etc/ipfw.rules
### rsync
$IPF 260 allow tcp from 192.168.1.2 to any 873 in

Rotate rsync log file:
# vim /etc/newsyslog.conf
/var/log/rsyncd.log 600 7 100000 * JC /var/run/rsyncd.pid

# /etc/rc.d/newsyslog restart

Setting up the client

You may have to install rsync on the client as well.. There wasn't much to set up on the client. I merely issued the following command. The rsync server in question is 192.168.1.1.

Create the password file first
# echo "mypass" > /usr/local/etc/rsyncd.passwd_rsync_bot1

Note: put password ONLY. Do NOT put username!

Perform a dry run (pseudo):
# rsync -navu --ipv4 --stats --safe-links --password-file=/usr/local/etc/rsyncd.passwd_rsync_bot1 rsync_bot1@192.168.1.1::web /www/rsync_tmp/

Note: -n parameter makes rsync perform a trial run preview that doesn't make any changes (and produces mostly the same output as a real run).

Pulling remote files from the remote rsync daemon:
# rsync -avu --ipv4 --stats --safe-links --password-file=/usr/local/etc/rsyncd.passwd_rsync_bot1 rsync_bot1@192.168.1.1::web /www/rsync_tmp/

Pulling remote files (use SSH connection):
# /usr/local/bin/rsync -avu --rsh="ssh -p 22" --ipv4 --stats --safe-links backuper@192.168.1.1:/home/backuper/backup/web-data/ /home/backuper/web-data/

Note: -a parameter turns on archive mode. Bascially this causes rsync to recurse the directory copying all the files and directories and perserving things like case, permissions, and ownership on the target. (Note: Ownership may not be preserved if you are not logged in as the root user.)

Note: -v parameter turns on verbose mode.

Note: the reason why I added the --safe-links parameter is because without it, the symbolic link files will be messed up.

Pushing local files to the remote rsync daemon:
# rsync -avu --ipv4 --stats --safe-links --password-file=/usr/local/etc/rsyncd.passwd_rsync_bot1 /www/rsync_tmp/ rsync_bot1@192.168.1.1::web

Note: do not forget the trailing slash of the directory path.

Rsync between two local directories:
# rsync -avu --ipv4 --stats --safe-links --iconv=CP950,utf-8 --exclude='*.svn' --exclude='*.log' /source/path/ /destination/path/

Note: if the filenames on the source server contain traditional chinese characters, make sure you do include the --iconv option.

To mount a remote Microsoft shared samba SMB / CIFS directories folders:
# mkdir /path/to/local/mnt
# mount_smbfs -f 400 -d 500 -I 1.2.3.4 //Username@NetBIOS-Server-Name/SharedFolder /path/to/local/mnt

-I 1.2.3.4 // Do not use NetBIOS name resolver and connect directly to host, which can be either a valid DNS name or an IP address.

Avoid password prompt:

Use smbutil to generate encrypted password:
# smbutil crypt MyPassword
$$14144762c293a0314e6e1

You need to create a ~/.nsmbrc file as follows:
# vim ~/.nsmbrc

Set username and password as follows:

[NetBIOS-Server-Name:Username]
password=$$14144762c293a0314e6e1

Now mount the directory as follows:
# mount_smbfs -f 400 -d 500 -N -I 10.1.2.3 //Username@NetBIOS-Server-Name/SharedFolder /path/to/local/mnt

The -N option forces to read a password from ~/.nsmbrc file. At run time, mount_smbfs reads the ~/.nsmbrc file for additional configuration parameters and a password. If no password is found, mount_smbfs prompts for it. You need to use the -N option while writing a shell script.

Note: ~/.nsmbrc Keeps static parameters for connections and other information. See /usr/share/examples/smbfs/dot.nsmbrc for details.

Note: man mount_smbfs

Mount the shared folder on system startup

mount_smbfs does not make the mount permanent. If the FreeBSD system is rebooted, you will have to mount the share again. To make the mount occur each time you start the FreeBSD system, you can put an entry in your /etc/fstab file. An example file would look like this:

//myUser@serverName/mySharedFolder /mnt/mySharedFolder smbfs rw,-N,-I192.168.1.1 0 0

If the share is password protected, don't forget to create ~/.nsmbrc with your usename and password.

Example:

From:
/some_path/test_link/

To:
/rsyncd-munged//some_path/test_link/

Other resource
# man rsync

# man rsyncd.conf

Connecting to remote rsync server via SSH

ServerA 192.168.1.1 // the server that is running rsync server.

ServerB 192.168.1.2 // the rsync client that is used for pulling and pushing files from the rsync server.

Pulling remote files from the remote rsync server:
ServerB # rsync -e ssh -avu --ipv4 --stats my_account@192.168.1.1:/www/rsync_tmp/ /www/rsync_tmp/

Pushing local files to the remote rsync server:
ServerB # rsync -e ssh -avu --ipv4 --stats /www/rsync_tmp/ my_account@192.168.1.1:/www/rsync_tmp/

Note: do not forget the trailing slash.

ServerB # ssh-keygen -t rsa

ServerB # scp ~/.ssh/id_rsa.pub my_account@192.168.1.1:/home/some_account

ServerA # cat id_rsa.pub >> ~/some_account/.ssh/authorized_keys2

ServerB # ssh my_account@192.168.1.1

=====================================================================

FAQ

Problem: name lookup failed for 192.168.100.157: hostname nor servname provided, or not known

Solution:
> Is there a way to prevent rsyncd from doing reverse IP lookups on
> connecting clients? I didn't find any config option for this.

There is no such option in the rsync code. I'd suggest adding any
local-net entries to your /etc/hosts file so that rsync's name lookup
uses that information.

Problem: secrets file must be owned by root when running as root (see strict modes)

Solution: Set both server side and client's secret file owned by root XD

Problem: ERROR: module is read only

Solution: add following line to the /usr/local/etc/rsyncd.conf file.
read only = no
=====================================================================

> > @ERROR: access denied to home from localhost (127.0.0.1)
>
> This is the important bit. This means that you got through
> to the rsync daemon and it rejected your access. The log
> file for the daemon will have more explicit information
> (which is hidden from the client on purpose), but I'd imagine
> that you need to add localhost to the list of acceptable IPs
> that are authorized to connect.

Rsync.conf
-------------------------------------------------
use chroot = no
strict modes = yes
auth users = backup
secrets file = /etc/rsyncd.secrets
hosts allow = *, localhost, 127.0.0.1, 192.168.180.53
log file = /var/log/rsyncd.log
max verbosity = 2
transfer logging = yes

[home]
path = /cygdrive/d/home/
exclude = .ssh/ .ssh/** TEST/ TEST/**
read only = no
timeout = 600
--------cut-other-modul-configuration---
========================================================================
- > I notice that the performance is pretty slow ranges between 2 and 6
> MB/s.
>
> The command that I use from a remote machine to this, the archiving
> host, is:
>
> rsync -avuz -e ssh ./dir archsrv:/archive/DATA
>
>
> An investigation with top shows that the system is cpu bound rather than
> IO bound and that the sshd process is consuming 75% of the CPU compared
> to the rsync process which uses about 25%.
>
> Why is ssh using so much CPU? It seems wrong to me. I would expect rsync
> to be using most as it has to do compression.

ssh has to do encryption, which is pretty CPU-intensive stuff.
You can tell ssh to use an encryption method that is less CPU-intensive,
such as arcfour; your command would look like this:

rsync -avuz -e 'ssh -c arcfour' ./dir archsrv:/archive/DATA

Alternatively, if security permits, use an rsync daemon.
======================================

Reference:
http://gala4th.blogspot.com/2010/02/rsync-synchronizing-two-file-trees_19.html
不使用密碼的SSH連線 - ssh-keygen
http://www.cyberciti.biz/faq/mounting-a-nas-with-freebsd-mount_smbfs/
http://blog.up-link.ro/freebsd-how-to-mount-smb-cifs-shares-under-freebsd/
http://www.freebsddiary.org/rsync.php
http://www.freebsddiary.org/secure-file-copy.php
http://www.freebsddiary.org/ssh-authorized-keys.php
http://blog.weithenn.org/2009/05/freebsdrsync.html
http://www.sanitarium.net/golug/rsync_backups_2010.html
http://slv922.pixnet.net/blog/post/26419814
http://lists.samba.org/archive/rsync/2005-October/013649.html