2008/06/27

我的心願

有一篇文章與大家分享,原文引自這裡,怕不見了就剪貼下來。在看文章之前,先說說我的心願,我是一直想跟朋友好好搞一下我的想法,建立一個虛擬世界。之前也不是沒有人想找我去負責當時流行的網路連線遊戲,只是我覺得那不是我真正想要的沒去。後來幾經週折,這幾年換工作快過什麼似的,目前,我只是想好好在現在的工作做個幾年,再累積一下人脈,若能工作與心願同時兼顧自然很好,若不能兼顧,就再晚個幾年吧。其實我的這心願存在不下十年了,我相信總有一天會實現的。這篇文章說的很好,希望將來我也能照亮別人。



玻璃業群聚 不斷寫奇蹟
‧Taiwan News 2008/06/26
「蠟燭不要一直拿在自己手上。一群人聚集在一起,把蠟燭逐一傳下,整群人都會被照亮,就算你手中沒有蠟燭,群聚就可以共享光明」。
【文/林明志】

中部濱海的中小企業 團結力量大

「蠟燭不要一直拿在自己手上。一群人聚集在一起,把蠟燭逐一傳下,整群人都會被照亮,就算你手中沒有蠟燭,群聚就可以共享光明」。林肇睢說,他大學時就喜歡登山,夜裡群聚在光亮處,夥伴共享共分攤,他說,群聚會產生巨大的力量,會在舞台發光發熱。

林肇睢是台灣首位實踐企業群聚的奇人,十年來,拿下世界最大家具品牌IEKA八○%的玻璃類產品,他說IEKA的十片玻璃,有八片是從他們手裡銷出去的。

十年前開始分享訂單

台明將十年前削價爭取到IEKA第一筆訂單一○○萬美金,同業分享訂單的原則進行玻璃群聚,十年後,IEKA的訂單多達四六○○萬美金,二○一三年,IEKA計畫將訂單量倍增到二億美金。

八十歲的IEKA創辦人坎普拉(Ingvar Kamprad)今年三月,特地從瑞典總部飛到台灣彰化,就是想一窺台灣玻璃產業的傳奇。

林肇睢是玻璃業界的奇人,中部業界喜歡稱呼他「大哥」。大哥不是混江湖;而是領導玻璃業界打拚,林肇睢為人四海,強調團結,他說,玻璃業是傳統企業,規模不大,想要生存就是團結打拚,就像打群架一樣,力量才能完全發揮,單打獨鬥容易遭到欺負。

從台明將公司說起,台明將前身為「信利行」,成立於民國三十二年,當時只不過是住家型的玻璃店,民國四十二年登記為「泉興鏡行」,七十三年正式成立「台明將企業」,現在的台明將資本額為一.五億,員工約一五○人,也是台灣玻璃龍頭台玻公司中部最大的經銷商。

台明將的成功之路

林肇睢說,從父親林將泉草創,他是二代接班,兒子林一翔退伍投入,家族三代在玻璃業界,從草創時期的四十坪廠房、二名員工,到今日漢寶本廠、一廠、彰濱工業區的玻璃館廠區,看盡玻璃產業的風華與慘淡及人間冷暖。

林肇睢輔仁大學體育系畢業,服完憲兵役退伍返鄉做玻璃,當時公司員工只有六人,專責從事玻璃販賣及簡易加工交易,由於人少事繁,父親每天都要清晨忙到晚,家族成員不眠不休的為公司打拚,林肇睢說,如果沒有突破,大家都會被累死、累病。

一定要突破規模與改變模式,是林肇睢始終存在的思維,他說︰「公司如果只能維持現狀,會累死老闆,損壞身體」「站在物競天擇,終有一天會被無情的淘汰」。林肇睢接管台明將之後,思考公司的長遠發展,與組織制度建立,他把「家族企業」轉化為「企業家族」,講究「傳賢不傳子」的經營理念。

「我不知道其他企業是怎麼經營?但我接管公司就是將經營權、所有權分離」簡單的說,就是員工與資方平均分享企業利潤,林肇睢的想法是,公司就是勞方與資方,不是誰較重要的問題,而是一樣份量,一樣共享共榮。台明將的員工分紅與資方一樣,不是資方取得絕對利潤後,再切割出員工享有的分紅,台明將的員工很喜歡此套模式,也很少人願意離開公司。

家族企業轉化為企業家族

家族企業轉化成企業家族,林肇睢說,玻璃業者要團結打拚,他把公司經營模式擴大到同業的結盟,協力廠商與台明將的份量是一樣的,他不是金字塔形的運作模式,台明將高高在上,而是環狀的配合模式,林肇睢解釋說,環狀的運作模式就沒有階級之分,產業策略是團結向國際競爭,這也是玻璃產業群聚的原始模型。

在台明將只有跟不上腳步的員工自動離職,林肇睢很少開除員工,在玻璃產業聚落裡,群聚的廠商對林肇睢信任,幾乎每位公司的管理階層,對林肇睢都豎起大拇指稱讚「大哥就是大哥」。林肇睢在大葉大學碩士進修,論文的專題就是他倡導的「產業群聚的效應」,目前他是彰師大機械所土博士班,專攻研究光學玻璃。

有人說,台明將不是玻璃業的大廠,資本額一億多,員工一百多人,卻有能力接下IEKA的千萬美金大單,IEKA的訂單每年都逐步增加,台明將到底怎麼辦到的?林肇睢說,表面上台明將不是大型企業,但是台明將背後的玻璃群聚業者,是最大的支柱,團結數十家,甚至上百家的中小型企業,不是可用資本額來計算的。

 林肇睢回憶,一九九八年,台明將以砍價二五%接下IEKA第一筆訂單,第二年與瑞典廠商比價,台明將再殺價三○%,二度爭取IEKA的訂單,瑞典的廠商原本擴充機器設備要與台明將比價,「瑞典廠商投資設備,就是為了接IEKA訂單,失去IEKA它什麼都沒有,只好宣佈倒閉!」林肇睢說,他就是帶領台灣玻璃業界打群架,IEKA的訂單就是我們的國際舞台。

隨時保持群聚優勢

IEKA訂單迷人卻有致命性,它的付款很乾脆,出貨二周內可以拿到貨款,但是採取全球開放競價,每年都會將產品的規格公開在網路上,歡迎全球供應商報價,能夠提供最好品質、準確交期與最低價格者,就有機會拿走訂單。IEKA的訂單策略,讓林肇睢戰戰兢兢,隨時保持群聚的優勢。

林肇睢說,每年競價取得的訂單,逐年增加,他所領軍的台灣玻璃群聚隨著增長,目前,台明將交付約三十家業者生產IEKA訂單,且代工IEKA的產值約佔每家代工廠的四成以上,林肇睢說,群聚最大的效應就是利潤共享,風險分攤,有錢大家做夥賺。

台明將是台玻公司的經銷商,同業需要的平板玻璃大都向台明將購買,因此台明將在業界的名聲很響,甚至南部業者都向台明將購買原料。林肇睢說,為了隨時支援玻璃同業生產所需,特別建構一個比台玻還要大的倉庫,庫存至少一萬二千噸,足以建造三棟台北一○一大樓,一○一大樓的玻璃外牆,約使用三千四百噸。

林肇睢說,他庫存大量的玻璃原料,是要做為群聚廠商的彈藥庫,也是設備的調度之一。他說,群聚廠商除了訂單的分享之外,包括設備、資金都是靈活支援調度,例如,群聚廠商需要生產設備,他會協助調度設備,折舊供給需要的廠商,另外,同業需要玻璃材料時,台明將會支援不預收現金,等到同業出貨收款之後再付錢給他。

協助業者站穩世界舞台

台明將的做法是不獨大,生產力彈性;同時降低風險,林肇睢說,訂單分享給同業,代表每個人都會賺錢,同樣代表風險分攤,不需要寡佔增加設備風險。有一次IEKA單品訂單原只有一百萬片,突然通知下個月要增到一千萬片,林肇睢說,一般業者根本無法接下單子,但是他們卻做到了,林肇睢通知群聚廠商增加產能,他們輕易通過考驗過關。

激增十倍的訂單,分攤給十多家業者,不需要太多壓力,但光靠單一廠商提供,根本無法交貨,況且新增生產線恐怕趕不上,如果訂單突然減少,閒置的設備成本,都會造成經營的困難。林肇睢的經營哲學,讓台灣玻璃中小企業站穩世界舞台,許多玻璃代工業者都想爭食IEKA大餅,但都無法順利取走訂單。

玻璃群聚走向彰濱工業區,為了加強運輸與材料支援,林肇睢首先響應進軍彰濱工業區設廠,他投資十二億買地蓋工廠,還到處遊說群聚廠商進駐,配合的廠商受到鼓舞,計有金潔明、福華、倩影等玻璃業者九家,廣義的玻璃相關業者包括鑄鋁、鐵管、玻璃與鏡子配套廠商等計有二十八家。

彰濱工業區原本未有玻璃加工專區,也因台明將領軍鼓舞業者進駐,工業區重新規劃設立「玻璃專區」。台灣玻璃業界的龍頭台玻公司,原本看淡台灣的玻璃產業到中國投資,十五年之後,台玻又在台灣投資二十億,重啟平板玻璃窯爐增產,且設置台玻鹿港彰濱廠,都是看中台明將倡導的玻璃群聚成果。

鼓勵業者留守台灣

林肇睢說,群聚越集中,發揮的力量與調度更靈活。台灣九○年代發生產業外移潮,台明將堅持不去中國,同時鼓勵業者留守台灣,以現今商場少見的義氣支持同業,讓群聚分享成長法則發揮到極致,十年來的努力,台明將的玻璃群聚打響國際知名度,誰也沒有想到,千萬美金龐大的產值,來自台灣中部濱海的中小企業,群聚的力量真可觀,它正在逐漸的壯大。

【更多精采內容請看《Taiwan News財經.文化週刊》第348期】

Bash 正規表示法的應用 -- 檢查 IP

本來譯自這裡, 原文的例子我個人覺得也沒什麼好的,就直接摘函式出來。

function valid_ip()
{
local ip=$1
local stat=1

if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
OIFS=$IFS
IFS='.'
ip=($ip)
IFS=$OIFS
[[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
&& ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
stat=$?
fi
return $stat
}


實際在用的時候,可以像:
if valid_ip $ip; then 成功之後做點事; fi
不過若是簡單的 if, 我通常用這種寫法:
[ valid_ip $ip ] && 成功之後做點事;

上面提供的 valid_ip() 說真的很單純,也不完整,例如要判斷 192.168.1.* 就不行,不過就是提供大家參考怎麼用正規表示法也還不錯。這個範例裡提到 $? 是上一個命令的結果(True/False), local ip=$1 是引用呼叫函數傳進來的第一個參數。

2008/06/20

在 Bash 中使用 Array

本文大約翻譯自這裡,一般人若習慣傳統 xSH 的話,那可能不會想要使用陣列。

Bash 提供一個方便的陣列表示法,雖然在使用上不像 Perl, Python, PHP, 甚至 C/C++, Java, JavaScript 等那麼自然,但是當您會使用陣列時,一些困擾也自然解決。

先來看看表示法:
arr=(Hello World)

主要特點是用小括號,元素間用空白(不限個數)隔開即可。若要個別指定值的話,也很直覺如下:

arr[0]=Hello
arr[1]=World


與別的語言相對上較不直覺得地方在於引用時的語法,底下的範例中大括號是必要的,雖然這在 shell Script 中很常見,但是整個寫起來還是有那麼一點不順眼,習慣就好了:

echo ${arr[0]} ${arr[1]}


底下看一些比較特別的用法,摘要說明在後面註解裡:

$ arr=(hello world) # 初始化陣列,示範與空白數無關
$ arr[5]=. # 讓陣列不連續
$ echo ${arr[*]} # 引用陣列中所有元素
hello world .
$ echo ${!arr[*]} # 引用陣列的所有索引值,因為個別指定時有可能讓陣列跳過某些元素
0 1 5
$ echo ${#arr[*]} # 取得元素個數
3
$ echo ${#arr[0]} # 取得某元素的長度
5


底下用一個完整的範例來說明陣列用法:

#!/bin/bash

array=(one two three four [5]=five) # [5] 的用法較特別,請思考思考

echo "Array size: ${#array[*]}"

echo "Array items:"
for item in ${array[*]}
do
printf " %s\n" $item
done

echo "Array indexes:"
for index in ${!array[*]}
do
printf " %d\n" $index
done

echo "Array items and indexes:"
for index in ${!array[*]}
do
printf "%4d: %s\n" $index ${array[$index]}
done

$ ./test.sh
Array size: 5
Array items:
one
two
three
four
five
Array indexes:
0
1
2
3
5
Array items and indexes:
0: one
1: two
2: three
3: four
5: five


底下再用一個範例來示範未使用雙引號及使用雙引號搭配 *, @ 的影響:

#!/bin/bash

array=("first item" "second item" "third" "item")

echo "Number of items in original array: ${#array[*]}"
for ix in ${!array[*]}
do
printf " %s\n" "${array[$ix]}"
done
echo

arr=(${array[*]}) # 引用所有元素展開後,因為元素值有空白,因而造成新陣列變異
echo "After unquoted expansion: ${#arr[*]}"
for ix in ${!arr[*]}
do
printf " %s\n" "${arr[$ix]}"
done
echo

arr=("${array[*]}") # 引用所有元素展開後,因為用雙引號括住,因而元素變成"一個"
echo "After * quoted expansion: ${#arr[*]}"
for ix in ${!arr[*]}
do
printf " %s\n" "${arr[$ix]}"
done
echo

arr=("${array[@]}") # 其影響請自行思考,非常重要
echo "After @ quoted expansion: ${#arr[*]}"
for ix in ${!arr[*]}
do
printf " %s\n" "${arr[$ix]}"
done

結果如下:
$ ./test2.sh
Number of items in original array: 4
first item
second item
third
item

After unquoted expansion: 6
first
item
second
item
third
item

After * quoted expansion: 1
first item second item third item

After @ quoted expansion: 4
first item
second item
third
item

2008/06/17

ooVoo? 視訊會議軟體

請參見 ooVoo

可以想成它跟 Skype, MSN 等軟體類似,用來做即時訊息傳遞,也包含 VIM 功能。底下翻譯一下其 features

.影像電話: 支援 HD 品質的影像電話
* 免費版一次可以跟三個人聊天(昇級後可以到六個人)
* 影像與聲音品質非常高且平順
* 沒人回話時(not on-line),可以留影像短片、聲音、或文字訊息
* 在視訊會議進行時,可同時傳送檔案或文字訊息(一如 Skype, MSN 等其它即時通)
* 可調整聲音或影像的輸出/輸入.
* 自訂電話鈴聲
* 可查詢對話歷程 (如未接來電,未通去電等).
* 視訊會議時可以調整影像特效

.錄影:昇級版方有此功能
* 可將影像電話(視訊會議)錄下來
* 錄影格式支援 AVI, FLV, 或 HTML embedded video.
* 最多可錄 1,000 分鍾的影像在 ooVoo 伺服器上,並且可以分享給別人,或在其他地方查詢

.影像訊息:
# 數量無限制的影像訊息,每則免費版上限一分鍾,昇級版五分鍾
# 可錄製並傳送給其他 ooVoo 好友,甚至包括未安裝 ooVoo 也行
# 一次傳送對象不受限制.
# 可在任何電腦播放影像訊息
# 可以儲存影像訊息在自己的電腦上
# 可將未錄製完成的影像訊息可以存在草稿區
# 創新你的生活。例如用影像訊息來製作邀請函,或廣告,或將你的旅行心得分享給其他人。

.影像特效:
* 例如更改大頭貼,加上帽子等等

.打電話:
* 可在北美地區,用來打電話,包括一般電話及手機

.文字模式即時通:
* 一次可與六個好友對話
* 容易邀請好友加入聊天室
* 可送訊息給離線好友

.傳送檔案:
* 傳送超大檔,最高到 25 MB
* 一次可傳送最多 20 個檔給多個好友
* 可傳送檔案給離線好友

.尋找好友:

.邊欄顯示:
* 將影像電話以邊欄顯示,儘量將桌面空出來

.公開您的 ooVoo 聯絡方式:
* 可放入任何 blog, 網頁,或是 email,甚至是簽名檔中
* 甚至可以指定「誰可以用 ooVoo 找我」

.隱私

如何把純文字檔放到 C 執行檔中?

請見 Embedding a File in an ExecutableConvert a File to a C Data Structure

一般方法至少三大類,最常見的就是利用 fopen 之類的 API 來自行處理 file I/O, 一種是第一篇文章說的,把 text file 轉成 object file 後再來引用指標的方式操作,一種是第二篇文章講的,將 text file 轉成 c char array struct。

先來看看文字檔,我改成多行:

$ cat data.txt
Hello, Wade.
This is a test line here
And this is the last line.
Add 4th line here.


底下是執行畫面,是在 cygwin 下執行的,因為 objcopy 的參數不太一樣,請修改成適當的,值得注意的是用 objdump 來看轉換後的 object file 內部的 symbol name 為 _binary_data_txt_start

$ objcopy.exe -I binary -O elf32-i386 -B i386 data.txt data.o

$ objdump.exe -x data.o

data.o: file format elf32-i386
data.o
architecture: i386, flags 0x00000010:
HAS_SYMS
start address 0x00000000

Sections:
Idx Name Size VMA LMA File off Algn
0 .data 00000054 00000000 00000000 00000034 2**0
CONTENTS, ALLOC, LOAD, DATA
SYMBOL TABLE:
00000000 l d .data 00000000 .data
00000000 g .data 00000000 _binary_data_txt_start
00000054 g .data 00000000 _binary_data_txt_end
00000054 g *ABS* 00000000 _binary_data_txt_size


底下列出測試用的 hello.c 及編譯、執行畫面,值得注意的是,因為 gcc 會在 extern symbol 前加上底線,因此命名方式跟原文不太一樣。


$ cat hello.c
#include

extern char binary_data_txt_start;
extern char binary_data_txt_end;

main()
{
char* p = &binary_data_txt_start;

while ( p != &binary_data_txt_end ) putchar(*p++);
}


$ gcc hello.c data.o

$ ./a
Hello, Wade.
This is a test line here
And this is the last line.
Add 4th line here.


第二種方式的 script 內容及執行畫面如下:

$ cat 2c.sh
#!/bin/bash

if [[ $# -ne 1 ]]; then
echo "Usage: $0 FILENAME"
exit 1
fi
file=$1

if [[ ! -f "$file" ]]; then
echo "File not found: $file"
exit 1
fi

cname=$file
cname=${cname//-/_}
cname=${cname//./_}

echo "static unsigned char $cname[] = {"
hexdump -v -e '" " 16/1 " 0x%02x, " "\n"' $file | \
sed -e '$s/0x ,//g'
echo "};"

$ ./2c.sh data.txt
static unsigned char data_txt[] = {
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x57, 0x61, 0x64,
0x65, 0x2e, 0x0a, 0x54, 0x68, 0x69,
0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x74, 0x65, 0x73,
0x74, 0x20, 0x6c, 0x69, 0x6e, 0x65,
0x20, 0x68, 0x65, 0x72, 0x65, 0x0a, 0x41, 0x6e, 0x64, 0x20,
0x74, 0x68, 0x69, 0x73, 0x20, 0x69,
0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x73, 0x74,
0x20, 0x6c, 0x69, 0x6e, 0x65, 0x2e,
0x0a, 0x41, 0x64, 0x64, 0x20, 0x34, 0x74, 0x68, 0x20, 0x6c,
0x69, 0x6e, 0x65, 0x20, 0x68, 0x65,
0x72, 0x65, 0x2e, 0x0a,
};

2008/06/02

大括號的擴展 Bash Brace Expansion

本文大致是翻譯自bash 大括號的擴展

Bash 的大括號擴展非常有用,常見場合是命令列或 shell script 中用於產生序列字串。語法不難明白,底下用實例解釋。


{aa,bb,cc,dd} => aa bb cc dd
{0..12} => 0 1 2 3 4 5 6 7 8 9 10 11 12
{3..-2} => 3 2 1 0 -1 -2
{a..g} => a b c d e f g
{g..a} => g f e d c b a


大括號的擴展也可以在字串中:

a{0..3}b => a0b a1b a2b a3b

也可以是巢狀的:

{a,b{1..3},c} => a b1 b2 b3 c

為瞭解釋方便,底下舉一個用大括號擴展的片段:
for i in {0..19}
do
echo $i
done


其相當的 for 迴圈寫法為:
for (( i = 0; i <>


也可以用 while 來表達:
while [[ $i -lt 20 ]]
do
echo $i
let i++
done


再用一個 seq 改寫 for 迴圈的例子說明:
for i in $(seq 0 19)
do
echo $i
done


事實上,上面的例子都只能用在數字的情況,若是非數字的部份則無法採用同樣的方式,例如:
for i in {a..z}
do
echo $i
done

個人比較常用於長路徑時使用,例如:
cp /a/long/path/A /a/long/path/B TARGET
寫成
cp /a/long/path/{A,B} TARGET

通常可以少打很多字

在寫 shell script 中,有時反而希望 BASH 不要解釋這樣的大括號擴展,可以用 set +B來抑制,也就是預設是 set -B來啟用

搭配中括號的擴展也會對有效字串的產生非常有幫助,請自行搭配使用。

2008/05/27

Bash Process Substitution 命令代換

本文大致是翻譯自shell process redirection


為瞭解釋方便,先假設有 a, b, 兩個純文字檔,內容為:

$ cat a
e
d
c
b
a
$ cat b
g
f
e
d
c
b


一般命令的轉向可以結合多個命令成一個,是非常方便的,可是這觀念在早期是從 stdin, stdout 來看才正確,若有個命令要用到 file 的話,就很麻煩,例如 comm 是比對兩個檔案,針對上面的 a, b 要比對的話,可能要先 sort a | uniq > tmp_asort b | uniq > tmp_b,之後再用 comm -3 tmp_a tmp_b

底下直接列出比較方便的方式:

comm -3 <(sort a | uniq) <(sort b | uniq)

說明:
<(command list) 會把命令結果當輸入,所以上面 <(sort a | uniq) 結果會被當成一個 file 供 comm 當輸入用 >(command list) 會把命令結果寫入

儲存空間共享 wuala

http://wua.la/

一般線上的儲存空間我就不多說,我是也有在用,只是很少真正拿來儲存檔案。早期我用過 gmail 來當儲存空間,叫 gdrive 或 gspace, 這跟 gfs 這個字無關。

wuala 是一個比較特別的儲存空間共享系統,可以在 Windows, Mac OS, Linux 上執行,它的理念是,你安裝後,可以免費取得 1G 的空間。對,你會想說這樣的空間並不大。所以真正有價值的理念是,它需要你貢獻你的儲存空間出來,若你貢獻了 10G, 而你平常「發呆」的時間夠長,譬如有一成的時間你可以給別人用的話,那你就可以增加 10G x 10% == 1G 的空間。

什麼?這有什麼好處?意思是,若你的電腦平時也都有開著,那你的發呆比例就會上升不是?那麼你可以使用的空間會多更多。往壞的方向想,你會說,那豈不是更浪費自己的儲存空間?要這麼想似乎也對,但是天下沒有白吃的午餐,當你把自己的空間貢獻出來的話,你就會獲得相對應大小的線上空間,這似乎才是比較長久的策略。

因為我還沒正式使用,只是先跟大家分享而已,有心得再跟大家報告。

正規表示法 regular expressions for bash

bash regular expressions

這篇主要算是翻譯自上面的文章。一般在寫 shell script 時,比對字串通常用的是 grep, sed, cut,col 等等工具,但是 Bash 較新的版本其實內建正規表示法運算子 =~ 可供使用,這有點像 perl, 但是又可以不必把龐大的 Perl 包裝進去。

因為正規表示法的比對是多匹配的,匹配結果放在 BASH_REMATCH 這個環境陣列變數中,整體結果放 BASH_REMATCH[0], 第一個匹配樣式放 BASH_REMATCH[1].....

直接給範例比較簡單:


#!/bin.bash
# saved as bashre.sh
if [[ $# -lt 2 ]]; then
echo "Usage: $0 PATTERN STRINGS..."
exit 1
fi
regex=$1
shift
echo "regex: $regex"
echo

while [[ $1 ]]
do
if [[ $1 =~ $regex ]]; then
echo "$1 matches"
i=1
n=${#BASH_REMATCH[*]}
while [[ $i -lt $n ]]
do
echo " capture[$i]: ${BASH_REMATCH[$i]}"
let i++
done
else
echo "$1 does not match"
fi
shift
done


執行結果如下:

$ ./bashre.sh 'aa(b{2,3}[xyz])cc' aabbxcc aabbcc
regex: aa(b{2,3}[xyz])cc

aabbxcc matches
capture[1]: bbx
aabbcc does not match

2008/04/02

shell script 的小技巧

假設有個 script file 如下:

#!/bin/sh
cmds.....

可以修成
#!/bin/sh -v
cmds.....

這樣就會自動把執行過程的命令列出來。第一行很重要,例如
#!/usr/bin/less
......

這樣就會把第二行以後(含)的所有內容,以 stdin 的方式傳給 less 讀。這種方法在寫 CGI 時其實很有用,好好思考一下運用起來就很方便。

2008/03/29

make -C

底下是用在 build mozilla 時用的,但是像 kernel 也是同樣的道理,參考一下

1) pull or update a tree from CVS
2) make -f client.mk build
3) go have lunch
4) make changes in foo/bar/
5) make -C foo/bar
6) repeat #4, #5

2008/03/28

message queue example

多年來,在做嵌入式產品時,經驗上在網虎時代大家都用 message queue 機制來通訊,其實當時也還有其他的機制,但是底下的工具可以讓大家省點事,似乎後來就都採用這套方法,有興趣的人可以拿去用用看。

語法在程式中有提到




#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#define MAX_TEXT 255

typedef struct my_msg_st {
long int mtype;
char mtext[MAX_TEXT];
} msgbuf;

int main(int argc, char *argv[])
{
int msgid;
int sz;
int key;
long int type;
msgbuf mdata;
char buffer[MAX_TEXT];

if (argc == 1) {
printf ("Usage: %s key [type [data]]\n", argv[0]);
return 1;
}

key = atoi (argv[1]);
msgid = msgget((key_t)key,0666|IPC_CREAT);

if (msgid == -1) {
return 2;
}

if (argc == 2) { // get all types
if (msgrcv(msgid,(void *)&mdata, MAX_TEXT, (long)0, IPC_NOWAIT) == -1) {
return 3;
}
printf ("%d %s\n", mdata.mtype, mdata.mtext);
}
else if (argc == 3) { // get assign type
type = atol (argv[2]);
if (msgrcv(msgid,(void *)&mdata, MAX_TEXT, type, IPC_NOWAIT) == -1) {
return 4;
}
printf ("%ld %s\n", mdata.mtype, mdata.mtext);
}
else if (argc == 4) { // send assign type, data
mdata.mtype = atol(argv[2]);
strcpy (mdata.mtext, argv[3]);
mdata.mtext[strlen(mdata.mtext)] = '\0';
if (msgsnd (msgid, (void *)&mdata, MAX_TEXT, IPC_NOWAIT) == -1 ) {
return 5;
}
printf ("send to msg_id %d with type %ld : '%s'\n", msgid, (long)mdata.mtype, mdata.mtext);
}
return 0;
} // end of main()

2008/01/10

如何突破防火牆

如何突破防火牆一向不是我關心的重點,不過公司也愈來愈誇張,東擋西擋的,現在我都不知道該怎麼上網了,連底下這篇也被擋,下面這篇絕不是我寫的。

如何突破防火牆設定
此篇文章並非小弟原創,原作者已不可考,它是我網管筆記的一部份分享給有需要的人

現在隨著人們的安全意識加強,防火牆一般都被公司企業採用來保障網路的安全,一般的攻擊者在有防火牆的情況下,一般是很難入侵的。下面談談有防火牆環境下的攻擊和檢測。

一 防火牆基本原理

首先,我們需要瞭解一些基本的防火牆實現原理。防火牆目前主要分包過濾,和狀態檢測的封包過濾,應用層代理防火牆。但是他們的基本實現都是類似的。

│ │---路由器-----網卡│防火牆│網卡│----------內部網路│ │

防火牆一般有兩個以上的網路卡,一個連到外部(router),另一個是連到內部網路。當打開主機網路轉發功能時,兩個網卡間的網路通訊能直接通過。當有防火牆時,他好比插在網卡之間,對所有的網路通訊進行控制。

說到訪問控制,這是防火牆的核心了:),防火牆主要通過一個訪問控制表來判斷的,他的形式一般是一連串的如下規則:

1 accept from+ 源位址,埠 to+ 目的地址,埠+ 採取的動作
2 deny ...........(deny就是拒絕。。)
3 nat ............(nat是位址轉換。後面說)

防火牆在網路層(包括以下的煉路層)接受到網路資料包後,就從上面的規則連表一條一條地匹配,如果符合就執行預先安排的動作了!如丟棄包。。。。
但是,不同的防火牆,在判斷攻擊行為時,有實現上的差別。下面結合實現原理說說可能的攻擊。

二 攻擊包過濾防火牆

包過濾防火牆是最簡單的一種了,它在網路層截獲網路資料包,根據防火牆的規則表,來檢測攻擊行為。他根據資料包的源IP位址;目的IP位址;TCP/UDP源埠;TCP/UDP目的埠來過濾!!很容易受到如下攻擊:


1 ip 欺騙攻擊:


這種攻擊,主要是修改資料包的源,目的地址和埠,模仿一些合法的資料包來騙過防火牆的檢測。如:外部攻擊者,將他的資料報源位址改為內部網路位址,防火牆看到是合法位址就放行了:)。可是,如果防火牆能結合介面,位址來匹配,這種攻擊就不能成功了:(


2 d.o.s拒絕服務攻擊


簡單的包過濾防火牆不能跟蹤 tcp的狀態,很容易受到拒絕服務攻擊,一旦防火牆受到 d.o.s 攻擊,他可能會忙於處理,而忘記了他自己的過濾功能。:)你就可以饒過了,不過這樣攻擊還很少的。!

3 分片攻擊

這種攻擊的原理是:在IP的分片包中,所有的分片包用一個分片偏移欄位標誌分片包的順序,但是,只有第一個分片包含有TCP埠號的資訊。當IP分片包通過分組過濾防火牆時,防火牆只根據第一個分片包的Tcp資訊判斷是否允許通過,而其他後續的分片不作防火牆檢測,直接讓它們通過。

這樣,攻擊者就可以通過先發送第一個合法的IP分片,騙過防火牆的檢測,接著封裝了惡意資料的後續分片包就可以直接穿透防火牆,直接到達內部網路主機,從而威脅網路和主機的安全。

4 木馬攻擊

對於包過濾防火牆最有效的攻擊就是木馬了,一但你在內部網路安裝了木馬,防火牆基本上是無能為力的。

原因是:包過濾防火牆一般只過濾低埠(1-1024),而高埠他不可能過濾的(因為,一些服務要用到高埠,因此防火牆不能關閉高埠的),所以很多的木馬都在高埠打開等待,如冰河,subseven等。。。

但是木馬攻擊的前提是必須先上傳,運行木馬,對於簡單的包過濾防火牆來說,是容易做的。這裏不寫這個了。大概就是利用內部網路主機開放的服務漏洞。

早期的防火牆都是這種簡單的包過濾型的,到現在已很少了,不過也有。現在的包過濾採用的是狀態檢測技術,下面談談狀態檢測的包過濾防火牆。

三 攻擊狀態檢測的包過濾

狀態檢測技術最早是checkpoint提出的,在國內的許多防火牆都聲稱實現了狀態檢測技術。

可是:)很多是沒有實現的。到底什麼是狀態檢測?一句話,狀態檢測就是從tcp連接的建立到終止都跟蹤檢測的技術。

原先的包過濾,是拿一個一個單獨的資料包來匹配規則的。可是我們知道,同一個tcp連接,他的資料包是前後關聯的,先是syn包,-》資料包=》fin包。資料包的前後序列號是相關的。

如果割裂這些關係,單獨的過濾資料包,很容易被精心夠造的攻擊資料包欺騙!!!如nmap的攻擊掃描,就有利用syn包,fin包,reset包來探測防火牆後面的網路。!

相反,一個完全的狀態檢測防火牆,他在發起連接就判斷,如果符合規則,就在記憶體登記了這個連接的狀態資訊(位址,port,選項。。),後續的屬於同一個連接的資料包,就不需要在檢測了。直接通過。而一些精心夠造的攻擊資料包由於沒有在記憶體登記相應的狀態資訊,都被丟棄了。這樣這些攻擊資料包,就不能饒過防火牆了。

說狀態檢測必須提到動態規則技術。在狀態檢測裏,採用動態規則技術,原先高埠的問題就可以解決了。實現原理是:平時,防火牆可以過濾內部網路的所有埠(1-65535),外部攻擊者難於發現入侵的切入點,可是為了不影響正常的服務,防火牆一但檢測到服務必須開放高埠時,如(ftp協議,irc等),防火牆在記憶體就可以動態地天加一條規則打開相關的高埠。等服務完成後,這條規則就又被防火牆刪除。這樣,既保障了安全,又不影響正常服務,速度也快。!

一般來說,完全實現了狀態檢測技術防火牆,智慧性都比較高,一些掃描攻擊還能自動的反應,因此,攻擊者要很小心才不會被發現。

但是,也有不少的攻擊手段對付這種防火牆的。

1 協議隧道攻擊

協議隧道的攻擊思想類似與VPN的實現原理,攻擊者將一些惡意的攻擊資料包隱藏在一些協定分組的頭部,從而穿透防火牆系統對內部網路進行攻擊。
例如,許多簡單地允許ICMP回射請求、ICMP回射應答和UDP分組通過的防火牆就容易受到 ICMP 和 UDP 協議隧道的攻擊。Loki和lokid(攻擊的用戶端和服務端)是實施這種攻擊的有效的工具。在實際攻擊中,攻擊者首先必須設法在內部網路的一個系統上安裝上lokid服務端,而後攻擊者就可以通過loki用戶端將希望遠端執行的攻擊命令(對應IP分組)嵌入在ICMP或UDP包頭部,再發送給內部網路服務端lokid,由它執行其中的命令,並以同樣的方式返回結果。由
於許多防火牆允許ICMP和UDP分組自由出入,因此攻擊者的惡意資料就能附帶在正常的分組,繞過防火牆的認證,順利地到達攻擊目標主機

下面的命令是用於啟動lokid伺服器程式:

lokid-p-I-vl

loki客戶程式則如下啟動:

loki-d172.29.11.191(攻擊目標主機)-p-I-v1-t3

這樣,lokid和loki就聯合提供了一個穿透防火牆系統訪問目標系統的一個後門。
2 利用FTP-pasv繞過防火牆認證的攻擊FTP-pasv攻擊是針對防火牆實施入侵的重要手段之一。目前很多防火牆不能過濾這種攻擊手段。如CheckPoint的Firewall-1,在監視FTP伺服器發送給用戶端的包的過程中,它在每個包中尋找"227"這個字串。如果發現這種包,將從中提取目標位址和埠,並對目標位址加以驗證,通過後,將允許建立到該位址的TCP連接。

攻擊者通過這個特性,可以設法連接受防火牆保護的伺服器和服務。詳細的描述可見

http://www.checkpoint.com/techsupport/alerts/pasvftp.html

3 反彈木馬攻擊

反彈木馬是對付這種防火牆的最有效的方法。攻擊者在內部網路的反彈木馬定時地連接外部攻擊者控制的主機,由於連接是從內部發起的,防火牆(任何的防火牆)都認為是一個合法的連接,因此基本上防火牆的盲區就是這裏了。防火牆不能區分木馬的連接和合法的連接。

但是這種攻擊的局限是:必須首先安裝這個木馬!!!所有的木馬的第一步都是關鍵!!!!

四 攻擊代理

代理是運行在應用層的防火牆,他實質是啟動兩個連接,一個是客戶到代理,另一個是代理到目的伺服器。

實現上比較簡單,和前面的一樣也是根據規則過濾。由於運行在應用層速度比較慢/1攻擊代理的方法很多。

這裏就以wingate為例,簡單說說了。(太累了)

WinGate是目前應用非常廣泛的一種Windows95/NT代理防火牆軟體,內部用戶可以通過一台安裝有WinGate的主機訪問外部網路,但是它也存在著幾個安全脆弱點。

黑客經常利用這些安全漏洞獲得WinGate的非授權Web、Socks和Telnet的訪問,從而偽裝成WinGate主機的身份對下一個攻擊目標發動攻擊。因此,這種攻擊非常難於被跟蹤和記錄。

導致WinGate安全漏洞的原因大多數是管理員沒有根據網路的實際情況對WinGate代理防火牆軟體進行合理的設置,只是簡單地從缺省設置安裝完畢後就讓軟體運行,這就給攻擊者可乘之機。

1 非授權Web訪問

某些WinGate版本(如運行在NT系統下的2.1d版本)在誤配置情況下,允許外部主機完全匿名地訪問網際網路。因此,外部攻擊者就可以利用WinGate主機來對Web伺服器發動各種Web攻擊(如CGI的漏洞攻擊等),同時由於Web攻擊的所有報文都是從80號Tcp埠穿過的,因此,很難追蹤到攻擊者的來源。

檢測

檢測WinGate主機是否有這種安全漏洞的方法如下:

1) 以一個不會被過濾掉的連接(譬如說撥號連接)連接到網際網路上。
2) 把流覽器的代理伺服器位址指向待測試的WinGate主機。
如果流覽器能訪問到網際網路,則WinGate主機存在著非授權Web訪問漏洞。

2 非授權Socks訪問

在WinGate的缺省配置中,Socks代理(1080號Tcp埠)同樣是存在安全漏洞。與打開的Web代理(80號Tcp埠)一樣,外部攻擊者可以利用Socks代理訪問網際網路。

防範

要防止攻擊WinGate的這個安全脆弱點,管理員可以限制特定服務的捆綁。在多宿主(multihomed)系統上,執行以下步驟以限定如何提供代理服務。

1選擇Socks或WWWProxyServer屬性。
2選擇Bindings標籤。
3按下ConnectionsWillBeAcceptedOnTheFollowingInterfaceOnly按鈕,並指定本WinGate服務器的內部介面。

非授權Telnet訪問

它是WinGate最具威脅的安全漏洞。通過連接到一個誤配置的WinGate伺服器的Telnet服務,攻擊者可以使用別人的主機隱藏自己的蹤跡,隨意地發動攻擊。

檢測

檢測WinGate主機是否有這種安全漏洞的方法如下:

1使用telnet嘗試連接到一台WinGate伺服器。


[root@happy/tmp]#telnet172.29.11.191
Trying172.29.11.191….
Connectedto172.29.11.191.
Escapecharacteris'^]'.
Wingate>10.50.21.5


2如果接受到如上的回應文本,那就輸入待連接到的網站。

3如果看到了該新系統的登錄提示符,那麼該伺服器是脆弱的。

Connectedtohost10.50.21.5…Connected
SunOS5.6
Login:


對策

防止這種安全脆弱點的方法和防止非授權Socks訪問的方法類似。在WinGate中簡單地限制特定服務的捆綁

就可以解決這個問題。一般來說,在多宿主(multihomed)系統管理員可以通過執行以下步驟來完成:

1選擇TelnetSever屬性。
2選擇Bindings標籤。
3按下ConnectionsWillBeAcceptedOnTheFollowingInterfaceOnly按鈕,並指定本WinGate服務器的內部介面。

2008/01/09

gnutella

這東西很好玩,主要在於有 source code, 而且不難,用來做 P2P, 就算只拿來研究檔案分享原理也不錯。

純文字版的有 mutella, 或有 GUI 的有 gtk-gnutella,有興趣研究的可以參考 http://gnutella-specs.rakjar.de/index.php/Main_Page

2008/01/02

AVI 轉換 DVD on Ubuntu

很好笑的一件事,同事用數位相機拍下 2007/2008 跨年煙火,卻不能在 windows 下用 media player 播放,我是懶得幫人家解決事情,教人家釣魚,不如直接給魚來的實際些,因此就將之轉成 DVD 格式,在此將心得寫下來。

第一步,先做好存放位置:
mkdir -p dvd

二、轉檔成 mpeg2
mencoder -oac lavc -ovc lavc -of mpeg -mpegopts format=dvd -vf scale=720:480,harddup -srate 48000 -af lavcresample=48000 -lavcopts vcodec=mpeg2video:vrc_buf_size=1835:vrc_maxrate=9800:vbitrate=5000:keyint=18:aspect=4/3:acodec=ac3:abitrate=192 -ofps 30000/1001 -o dvd.mpg xxx.avi

mencoder -oac copy -ovc lavc -of mpeg -mpegopts format=dvd -vf scale=720:480,harddup -lavcopts vcodec=mpeg2video:vrc_buf_size=1835:vrc_maxrate=9800:vbitrate=5000:keyint=18:aspect=4/3 -ofps 30000/1001 -o dvd.mpg xxx.avi

三、準備 xml 檔以便轉成 DVD

<dvdauthor>
<vmgm />
<titleset>
<titles>
<pgc>
<vob file="dvd.mpg" chapters="0,0:10,0:20,0:30,0:40,0:50" />
</pgc>
</titles>
</titleset>
</dvdauthor>


四、轉成 DVD 格式
dvdauthor -o dvd -x dvd.xml

五、試播(可略過)
mplayer dvd:// -dvd-device ./dvd

六、燒錄
growisofs -dvd-compat -Z /dev/scd0 -dvd-video ./dvd/
PS: /dev/scd0 應視您的系統而定,指的是燒錄機的實體裝置名稱

2007/12/13

active RAID-5 ubuntu with mdadm

想在 ubuntu 下裝 RAID-5 的企圖心讓我有機會第一次設定 Raid-5, 在此建議各位使用 mdadm, 若尚未安裝的話,請 sudo apt-get install mdadm

步驟很簡單,只需要先將硬碟裝起來,當然驅動程式不在此討論。以我的例子來說,我是裝了四顆硬碟,用 fdisk -l 看會有四顆硬碟。

二、先分割區做好,例如 fdisk /dev/sdf。請把四顆都做好,而不是一顆。至於分割區的 type, 請選擇 fd. 不過我用 ext3(83) 也可以。

三、mdadm -C /dev/md0 -l5 -n4 /dev/sd[bcde]1

四、使用前當然要先格式化 mkfs.ext3 /dev/md0

四、接下來就可以掛載 mkdir -p /media/raid5; mount /dev/md0 /media/raid5

五、要停用的話,請用 mdadm --stop, 若要重新啟用則用 mdadm --run,有一個建議的用法是 mdadm --stop --scan 這樣可以把所有 RAID 停掉

六、若要自動在開機時掛載(非從此 RAID 碟開機)的話,可以修改 /etc/fstab, 參考如下
/dev/md0 /media/raid5 auto defaults 0 0

七、要若查狀態,可以用 mdadm -D /dev/md0

八、若是將 RAID 硬碟移到別的系統,則需要重組 mdadm --assemble --scan

九、若要把 RAID 電源關閉,必須先移除該 RAID controller 的 module, 否則核心會收到一堆錯誤訊息,以我的系統為例,是 rmmod sata_sil24。當然若你系統未關,在重新使用 RAID 之前記得先 modprobe sata_sil24。因為 RAID 都是 SATA 裝置,所以若不知道自己的模組名稱,可以試試 lsmod | grep sata 來找出來

蛇吞象 400S, ubuntu-7.10-server Sil 3132 + Sil 3726

我想架個 server, 做法是買台 普通 DIY PC, 然後外掛一台蛇吞象 400S, 裡面接四顆 500GB 硬碟,這樣的好處是 PC 沒附作業系統,我喜歡,而儲存用的硬碟在外面也比較好管理。

問題來了,這款 Raid 外接盒並沒有受支援,找了 patch file 一看,哇,一萬七千多行,我用差不多一天的時間才 porting 完,下載最新 2.6.23 更新檔,但是我想既然要更新,就將它更新到 2.6.39.9 的最新版去。幸好開機成功。

若有興趣的人,請自行下載 patch, 不過原網站目前最新的是給 2.6.23, 若您想用 2.6.23.9 試試的話,可以從此處下載。請注意兩件事:
一、這個 patch 並未給予任何保證與服務
二、裡面我拿掉一個裝置,p5wdh, 懶得把它加回去。

2007/12/06

gmail group chat

愛用 google 產品的注意一下。我五、六年前開始用 google 的 search engine 時就已發現英文介面(一開始其實沒中文介面)與中文介面設定畫面不太一樣,尤其在從試用版開始用 gmail 時也發現所提供的功能也不太一樣。但是因為當時查兩種語系的功能時發現不同的部份我也用不到,所以後來只用中文介面,誰知,今天為了要找 gmail group chat 功能才發現,事實上還不止這個功能在中文沒有,還有更多的地方是不一樣的。

也就是說,請大家有機會有意願的話,用英文介面吧!

2007/12/05

VirtualBox 使用 usb device

http://www.linuxdiyf.com/viewarticle.php?id=67813
1.增加 usbfs 群組

$ sudo groupadd usbfs
# groupadd usbfs

2. 查看 usbfs 的 gid

$ cat /etc/group | grep usbfs
usbfs:x:1002: <-- 這邊應該會不一樣,請仔細比對,下面要用到

把當前用戶增加到 usbfs 群組,請修改 /etc/group 裡的
usbfs:x:1002:
修改為
usbfs:x:1002:wade 這裡的 wade 即為你平常登入使用的帳號

4. 為 USB 裝置檔案系統設置掛載及權限,修改 /etc/fstab文件,添加下面兩行,注意你的gid可能不是1002(上面有查到)

# 1002 is the USB group IDI
none /proc/bus/usb usbfs devgid=1002,devmode=664 0 0

2007/11/30

模擬器 simulator

一聽到模擬器,大家會想到的或許是game 的吧,但是我一向不玩 game, 所以當然不會去談它,但是事實上我也曾經玩過 game 模擬器,其實這也是一個課題。

比較常用的模擬器有很多,一般人可能較常用 vmware 吧,不過我以前只用 wine, 後來用 qemu, 最近又多了一個不錯的選擇,叫 virtual box, 有windows 也有 Linux, 例如 debian/ubuntu

其實模擬器還有很多,例如 xen, 但是其他的我都沒在用,只曾經試用。若以 x86 的模擬來說,Virtual box 比 qemu 還快,不過 qemu 適用的硬體較多,算是各有好壞。