如何才能防止 cgi 資料不會遺失?





閃客
2001-05-09, 09:47 AM
我的討論區 cgi 程式一段時間會有資料遺失的現象,
可是檔案都存在,只是列表資料有遺失,懷疑是有人破壞,
請問他是如何辦到的呢? 有沒有辦法預防.....
我已經換了好幾個 cgi 了....




xbug
2001-05-09, 01:12 PM
我個人經驗, 發生這種情況大都是 cgi 程式設計不良的因素, 問題應該出在 filelock 的部份..

閃客
2001-05-09, 04:30 PM
我有使用 flock 可是還是會有資料遺失的現象...
有沒有其他補救辦法呢?

xbug
2001-05-09, 06:21 PM
不知道您是在什麼系統上執行, windows 95/98/se/me 是不支援 flock 的。
如果不是那我也只能建議再確認一次, 在讀/寫檔案前是否確定都有做 flock 。
另外如果您是自己處理記錄檔, 而不是採用MySql等database,
也check看看是否有可能是邏輯或程式流程方面的錯誤,
例如:

f_lock()
ReadFile(a.txt)
f_unlock()
//處理讀到的檔案資料
f_lock()
WriteFile(a.txt) // 寫入處理過的資料
f_unlock()

這樣的架構就可能會出問題, 如果改成:

f_lock()
ReadFile(a.txt)
//處理讀到的檔案資料
WriteFile(a.txt) // 寫入處理過的資料
f_unlock()

這樣的架構就安全的多。
不知對您是否有用, 參考參考就好。

閃客
2001-05-09, 06:32 PM
我的 cgi 是在 unix 上面 run...
程式這樣寫有漏洞嗎?
open (DATA,">$datafile");
flock(DATA,2);
...
...
...
flock(DATA,8);
close (DATA);

謝謝您這麼熱心回答我的問題 ^^~
麻煩您了!

xbug
2001-05-10, 03:24 PM
以寫入的程序來看,你的寫法是沒問題的。
我的意思是指像下面這個程式的情況...

for ($i=1; $i<50000; $i++) {
$txt = &readdata; # 讀a.txt
$txtLng = length($txt);
if ($txtLng == 0) { # 如果a.txt檔案size == 0
print "Error: $i\n";
last; # 離開迴圈
}
else {
print "$txt\n";
}
$txt++; # 將讀到的值加 1
&writedata($txt); # 寫回 a.txt
}

sub readdata {
unless (-e "a.txt") { # 如果 a.txt 不存在
return 0;
}
else {
open (DATA,"a.txt");
flock(DATA,2);
$text=<DATA>;
flock(DATA,8);
close(DATA);
return $text;
}
}

sub writedata {
open (DATA,">a.txt");
flock(DATA,2);
print DATA "$_[0]";
flock(DATA,8);
close (DATA);
}

這個程式的功用很簡單, 在單 thread 的環境中能執行得很好不會有任何問題, 可是如果開2個以上 thread 去跑, 就可能會碰到讀取的a.txt檔案大小為0, 導致

if ($txtLng == 0) { # 如果a.txt檔案size == 0
print "Error: $i\n";
last;
}

條件成立, 使得程式提前結束, 我在想你比較有可能是碰到類似的問題。
-----------------------------------------------------

另外, 你的程式在 open datafile 之後一定要確認有 close 的動作才行, 注意這種情況:

open (DATA,">$datafile");
flock(DATA,2);
...
## 因為發生錯誤直接 return 回主程式,所以忘了 close
return if (發生錯誤);
return if (開啟檔案b錯誤);
...
flock(DATA,8);
close (DATA);

-----------------------------------------------------

ps. 如果還繼續討論, 是否換個版面? 在 anti-hacker 板討論好像不太對.. ^^!