<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-37459183</id><updated>2012-02-10T23:58:27.655+11:00</updated><category term='Social'/><category term='Software Engineering'/><category term='đóng bụi'/><category term='Linux'/><title type='text'>A place for friends...</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://conmale.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://conmale.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>conmale</name><uri>http://www.blogger.com/profile/16598933828282382048</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/-2pIWb2iUysc/TzSYz5aVJYI/AAAAAAAAAAQ/BCWx8yVHmbU/s220/me.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>19</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-37459183.post-4887816307517367238</id><published>2012-02-10T17:01:00.000+11:00</published><updated>2012-02-10T17:03:28.310+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='đóng bụi'/><title type='text'>Cái blog đóng bụi</title><content type='html'>Hôm nay chợt nhớ đến cái blog ngày xa xưa. Thử "login", chà... vẫn đăng nhập được. Chỉ có điều, google bắt mình phải đổi account bởi vì account ngày xa xưa cũng chẳng còn nữa.&lt;br /&gt;&lt;br /&gt;Thôi... phủi bụi và bắt đầu viết lại. Biết đâu ngày nào đó vẫn còn hữu dụng.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37459183-4887816307517367238?l=conmale.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://conmale.blogspot.com/feeds/4887816307517367238/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37459183&amp;postID=4887816307517367238' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/4887816307517367238'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/4887816307517367238'/><link rel='alternate' type='text/html' href='http://conmale.blogspot.com/2012/02/cai-blog-ong-bui.html' title='Cái blog đóng bụi'/><author><name>conmale</name><uri>http://www.blogger.com/profile/16598933828282382048</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/-2pIWb2iUysc/TzSYz5aVJYI/AAAAAAAAAAQ/BCWx8yVHmbU/s220/me.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37459183.post-2269062285177338743</id><published>2008-04-02T11:08:00.001+11:00</published><updated>2008-04-02T11:10:48.684+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>Craftsman 4 - A Test of Patience</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: verdana;"&gt;Robert C. Martin&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;12 tháng 7, 2002&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Nhật ký thân yêu,&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tối qua tôi ngồi tựa cửa sổ hàng giờ, nhìn các vì sao mờ dần trong bầu trời đêm. Tôi thấy việc làm của tôi và Jerry hôm qua có nhiều xung đột. Tôi học hỏi rất nhiều trong khi làm việc với Jerry với vấn đề tạo số nguyên tố, nhưng tôi không tin tôi gây ấn tượng gì với gã. Và, thật tình mà nói, tôi cũng không nể gã cho lắm. Thật ra, gã tốn khá nhiều thời gian mài dũa các mảnh mã cho dù những mảnh mã này làm việc ngon lành.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Hôm nay với một bài tập mới, Jerry đến gặp tôi. Gã yêu cầu tôi viết một chương trình tính thừa số nguyên tố của số nguyên. Gã cho biết gã làm việc với tôi ngay từ đầu nên hai chúng tôi ngồi xuống và bắt đầu lập trình.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tôi tin chắc tôi biết cách làm. Hôm qua chúng tôi đã viết chương trình tạo số nguyên tố. Dò tìm các thừa số nguyên tố chỉ là vấn đề đi xuyên qua danh sách các số nguyên tố và xét thử có thừa số nào từ các số nguyên đã định. Thế nên tôi vớ lấy bàn đánh và bắt đầu viết mã. Khoảng nữa giờ sau khi viết và kiểm tra, tôi làm được như sau:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;import java.util.Iterator;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;import java.util.LinkedList;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;import java.util.List;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;public class PrimeFactorizer {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  Public static void main(String[] args) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    int[] factors = findFactors(Integer.parseInt(args[0]));&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    for (int i = 0; i &lt;&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  Public static int[] findFactors(int multiple) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    List factors = new LinkedList();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    int[] primes = PrimeGenerator.generatePrimes((int) Math.sqrt(multiple));&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    for (int i = 0; i &lt;&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;      for (; multiple % primes[i] == 0; multiple /= primes[i])&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;        factors.add(new Integer(primes[i]));&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    return createFactorArray(factors);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  private static int[] createFactorArray(List factors) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    int factorArray[] = new int[factors.size()];&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    int j = 0;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    for (Iterator fi = factors.iterator(); fi.hasNext();) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;      Integer factor = (Integer) fi.next();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;      factorArray[j++] = factor.intValue();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    return factorArray;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tôi kiểm tra chương trình bằng cách chạy nó với nhiều thông số khác nhau. Mọi thứ dường như ổn thoả. Chạy chương trình với giá trị thông số 100 cho tôi kết quả 2, 2, 5 và 5. Chạy nó với 32767 cho tôi 7, 31 và 151. Chạy với 32768 cho tôi mười lăm số hai.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Jerry ngồi nhìn tôi. Gã chẳng nói nửa lời. Ðiều này làm tôi hơi hoảng nhưng tôi tiếp tục nắn bóp và thử nghiệm mã nguồn cho đến lúc tôi hài lòng. Sau đó, tôi bắt đầu viết phần "unit tests".&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Jerry hỏi: "Mày làm gì vậy?"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;"Chương trình chạy nên tôi đang viết các unit tests." Tôi đáp lại.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;"Nếu chương trình đã chạy việc gì mày cần unit tests?" Gã hỏi tiếp.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tôi không nghĩ đến điểm này. Tôi chỉ biết theo thông lệ cần phải viết unit tests. Tôi liều lĩnh đoán mò: "Ðể mà các lập trình viên khác biết được là chương trình đó chạy?"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Jerry nhìn tôi khoảng 30 giây rồi gã lắc đầu và nói: "Thời buổi này họ dạy dỗ tụi mày cái gì ở trường vậy?"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tôi đớ lưỡi không trả lời được nhưng gã ngăn tôi lại bằng một cái nhìn.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;"OK", gã nói, "xoá hết những thứ mày đã làm đi. Tao chỉ cho mày cách tụi tao làm ở đây."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tôi quả không chuẩn bị cho tình thế như vậy. Gã muốn tôi xoá những gì tôi đã tạo ra trong ba mươi phút qua. Tôi chỉ ngồi yên, không tưởng tượng nổi.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Cuối cùng Jerry nói: "Xoá đi."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tôi trả lời: "Nhưng chương trình đó chạy mà."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;"Thì sao?" Jerry đáp lại.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tôi bắt đầu nổi cáu. Tôi nói cứng: "Chương trình này chẳng có gì sai hết!"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;"Thực vậy hở?" gã lầm bầm và vớ lấy bàn đánh, xoá hết mã nguồn của tôi.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tôi điếng người. Không phải, tôi điên tiết lên. Gã mới vừa chồm qua và xoá hết đồ của tôi. Trong phút chốc ấy tôi chẳng còn thiết gì đến ưu thế được làm một tay học việc cho ông C nữa. Học việc mà phải đụng đến những kẻ tàn bạo như Jerry thì còn hay ho gì nữa? Với ý nghĩ như thế và những ý nghĩ còn kém phần tưởng thưởng khác diễn nhanh qua trong đầu trong khi tôi nhìn gã chằm chặp.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;"À, tao thấy mày nổi đoá rồi đó." Jerry nói một cách điềm tĩnh.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tôi lắp bắp nhưng chẳng thốt được gì cho minh bạch.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;"Này." Jerry nói, rõ ràng đang cố làm dịu tôi xuống. "Ðừng có đeo cứng vào mã nguồn của mà quá như vậy. Chỉ có ba mươi phút làm việc mà thôi chẳng phải là cái gì ghê gớm đâu. Mày phải chuẩn bị tinh thần vứt bỏ thêm cả đống mã nguồn nữa nếu mày muốn trở thành một thứ lập trình viên gì đó. Vứt bỏ được hàng đống mã nguồn thường là điều tốt nhất mà mày nên làm.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tôi buộc miệng: "Nhưng làm như thế thì quả là phí!"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Gã hỏi lại: "Bộ mày nghĩ giá trị của chương trình nằm trong mã nguồn sao? Không phải vậy. Giá trị của một chương trình nằm trong cái đầu của mày đó."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Gã nhìn tôi chừng một giây rồi tiếp tục. "Có bao giờ mày lỡ tay xoá cái gì đó mày đang làm chưa? cái gì đó mất của mày vài ngày làm việc đó?"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;"Có một lần, ở trường". Tôi nói "Cái disk bị hỏng và hồ sơ lưu trữ cũ đến hai ngày."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Gã cau mày gật đầu biểu lộ sự thông hiểu rồi hỏi: "Mày mất bao lâu để tái tạo lại những cái đã bị mất?"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;"Tôi nắm khá rõ những cái bị mất nên chỉ mất có nửa ngày để tái tạo."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;"Ra thế mày chẳng thật sự mất khối lượng hai ngày làm việc."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tôi chẳng màng gì đến cái logic của gã. Tôi không bắt bẻ được nhưng tôi không khoái cái logic đó. Chỉ đơn giản là tôi cảm thấy bị mất một khối lượng hai ngày làm việc!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Gã hỏi tiếp: "Mày có nhận thấy phần mã làm lại tốt hơn hay tệ hơn phần mã mày bị mất không?"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;"Ồ, tốt hơn nhiều." Tôi nói, ngay lập tức hối tiếc là đã phát biểu như thế. "Lần thứ nhì tôi có thể dùng một cấu trúc tốt hơn nhiều."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Gã cười. "Thế thì cố thêm 25 phần trăm, mày đưa ra được một giải pháp tốt hơn."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Logic của gã làm tôi bực mình. Tôi lắc đầu và gần như thét lên: "Có phải ông giả định là chúng ta luôn luôn vứt bỏ mã nguồn sau khi làm xong?"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Trả lời cho sự ngạc nhiên của tôi, gã gật đầu và nói: "Gần như là như vậy. Tao giả định chuyện vứt bỏ mã nguồn là một việc giá trị và hữu dụng. Tao giả định mày không nên xem đó là chuyện hoang phí. Tao giả định mày không nên ôm khư khư cái mã nguồn của mày."&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37459183-2269062285177338743?l=conmale.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://conmale.blogspot.com/feeds/2269062285177338743/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37459183&amp;postID=2269062285177338743' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/2269062285177338743'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/2269062285177338743'/><link rel='alternate' type='text/html' href='http://conmale.blogspot.com/2008/04/craftsman-4-test-of-patience.html' title='Craftsman 4 - A Test of Patience'/><author><name>conmale</name><uri>http://www.blogger.com/profile/16598933828282382048</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/-2pIWb2iUysc/TzSYz5aVJYI/AAAAAAAAAAQ/BCWx8yVHmbU/s220/me.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37459183.post-4327896760768254368</id><published>2008-04-02T11:01:00.002+11:00</published><updated>2008-04-02T11:07:28.656+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>Craftsman 3 - Clarity and Collaboration</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;i style="font-family: verdana;"&gt;Lần trước, Jerry, một cựu học việc yêu cầu tay học việc Alphonse viết một chương trình tạo số nguyên tố dùng phương pháp lượt Eratosthenes (sieve of Eratosthenes). Jerry duyệt và giúp Alphonse tách lược (refactor) mã nguồn đó. Anh ta không được hài lòng với kết quả của Alphonse. Lần trước Alphonse thực hiện xong phần refactoring và nghĩ chắc Jerry sẽ chấp thuận...&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Jerry chỉ thoáng gật đầu. Liệu gã có thật sự khoái những điều tôi đã làm không?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Sau đó Jerry đi xuyên qua trọn bộ chương trình, đọc lại từ đầu đến cuối như thể gã đang đọc bài chứng minh hình học. Gã bảo tôi đây là một bước hết sức quan trọng. "Ðến bước này, tụi mình đã thực hiện refactoring các mảnh mã. Bây giờ tụi mình xem thử trọn bộ chương trình có thể nối liền nhau như một dạng tổng thể".&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tôi hỏi: "Jerry, bộ ông cũng làm như thế với chính mã nguồn của ông sao?"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Jerry quắc mắt lên và nói: "Ở đây tụi tao làm việc với nhau theo nhóm nên không có cái mã nào là của riêng tao hết. Bộ mày cho là cái mã này của riêng mày hở?"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tôi trả lời hết sức nhỏ nhẻ: "hết nghĩ như vậy rồi, ông ảnh hưởng rất lớn đến mã nguồn này."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Gã trả lời: "Cả hai thằng mình đều ảnh hưởng đến nó, và đây là cách ông C ưa chuộng. Ông ấy không khoái bất cứ một ai làm chủ mã nguồn hết đâu. Trả lời riêng cho câu hỏi của mày: Ðúng vậy, ở đây tụi tao thực nghiệm cái "rơ" refactoring và dọn rác và đây là phương pháp của ông C."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Trong khi đọc qua mã nguồn, Jerry thấy gã không khoái cái tên &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;initializeArrayOfIntegers&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Gã nói: "Cái được khởi tạo ở đây thực ra không phải là một dãy số nguyên, mà là một dãy booleans. Nhưng &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;initializeArrayOfBooleans&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; không hẳn là cách cải tiến. Ðiều chúng ta thực sự muốn làm ở method này là liệt kê ra một danh sách các số nguyên phù hợp và để chúng lên một cái sàng, rồi sau đó lọc và loại ra các số không phải số nguyên tố (ie loại ra những bội số)". (Do đó, danh sách lúc đầu sẽ không bị gạch chéo, những số bị loại sẽ sẽ bị gạch chéo (crossed out )).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tôi trả lời: "Tất nhiên!" Thế là tôi vớ lấy bàn đánh và sửa tên của method đó thành &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;uncrossIntegersUpTo&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Tôi cũng thấy không khoái cái tên &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;isCrossed&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; lại dùng cho một dãy booleans, nên tôi đổi nó thành &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;crossedOut&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Các cái test vẫn chạy. Tôi bắt đầu thấy thích mấy cái trò này nhưng Jerry vẫn không hề tỏ vẻ đồng tình.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Sau đó Jerry quay lại, hỏi tôi có phải tôi đã mơ màng theo khói thuốc khi viết cái mớ &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;maxPrimeFactor&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. (Xem &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;mã dẫn 6&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;). Thoạt đầu tôi hết sức ngỡ ngàng nhưng khi xem lại đoạn mã và các phụ chú tôi nhận thấy gã có lý. Eo ôi, tôi thấy mình thật là ngu! Căn bậc 2 (Square root )* của chiều dài một dãy số không hẳn là nguyên số. Method đó không tính thừa số nguyên tố cực đại (max prime factor) **. Phần chú giải sai bét nên, hết sức ngượng ngùng tôi viết lại phần phụ chú để giải thích rõ hơn cái căn bậc 2 này dùng để làm gì và đổi tên những biến , hàm cho thích hợp. Các test vẫn chạy.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Mã dẫn 6:&lt;/b&gt;&lt;br /&gt;&lt;code style="font-family: courier new;"&gt;TestGeneratePrimes.java (Partial)&lt;br /&gt;    private static int calcMaxPrimeFactor() {&lt;br /&gt;&lt;br /&gt;       // We cross out all multiples of p, where p is prime.&lt;br /&gt;       // Thus, all crossed out multiples have p and q for factors.&lt;br /&gt;       // If p &gt; sqrt of the size of the array, then q will never&lt;br /&gt;       // be greater than 1. Thus p is the largest prime factor&lt;br /&gt;       // in the array, and is also the iteration limit.&lt;br /&gt;&lt;br /&gt;       double maxPrimeFactor = Math.sqrt(isCrossed.length) + 1;&lt;br /&gt;       return (int) maxPrimeFactor;&lt;br /&gt;    }&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;"dùng +1 ở đây làm quái gì vậy?" Jerry tru tréo lên.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tôi nuốt cái ực, xem lại đoạn mã và cuối cùng tôi phát biểu: "Tôi ngại là khi chỉ lấy phần nguyên của căn bậc 2, thì phần thập phân của căn bậc 2 đó bị mất đi, do đó vòng lặp có thể bị thiếu."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Gã bèn hỏi: "Cho nên mày xả rác trong đoạn mã với phần gia tăng "+1" bởi vì mày bị hoảng? Như thế thì ngốc quá, dẹp ngay cái trò gia tăng "+1" đó đi và thử test lại."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tôi làm như thế và trọn bộ các test đều chạy. Tôi suy nghĩ lại phần này một lúc vì nó làm tôi run quá. Thế nhưng tôi quyết định có thể giới hạn lặp lại thực sự chính là số "thừa số nguyên tố cực đại" và "thừa số nguyên tố" đó &lt;= căn bậc 2 chiều dài của dãy số.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;"Phần thay đổi vừa rồi làm tôi khá bối rối". Tôi nói với Jerry. "Tôi hiểu nguồn gốc đằng sau cái căn bậc 2, nhưng tôi cảm thấy không yên, biết đâu có trường hợp "biên" nào đó mình chưa thấy hết."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Gã lầm bầm "OK, vậy thì viết một cái test khác để kiểm tra chuyện đó đi."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;"Tôi nghĩ tôi có thể kiểm tra xem trong các danh sách số nguyên từ 2 đến 500 không có trường hợp ở trên". &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;"OK, nếu nó làm cho mày cảm thấy dễ chịu hơn, thì thử đi." Gã nói. Rõ ràng là gã bắt đầu trở nên mất kiên nhẫn.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Thế là tôi viết cái &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;testExhaustive&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; function như trong &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;mã dẫn 8&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Phần test mới này chạy đúng và nỗi lo sợ của tôi lắng xuống.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Jerry dịu xuống một chút. Gã nói: "Biết được lý do tại sao một cái gì đó chạy được luôn luôn là một điều tốt; và lại càng tốt hơn khi mà kiểm chứng được mày đúng bằng cái test."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Sau đó Jerry dò qua trọn bộ mã nguồn và các cái tests một lần nữa (xem &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;mã dẫn 7 và 8&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;). Gã ngã người ra và suy nghĩ chừng một phút rồi nói: "OK, tao nghĩ là tụi mình làm xong. Mã nguồn này xem ra đủ rõ ràng (clean) rồi đó. Tao sẽ đưa cho ông C xem."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Thế rồi gã nhìn tôi, lạnh lùng nói: "Phải nhớ, từ nay về sau khi mày viết một phần nào đó, nên tìm sự giúp đỡ và nhớ giữ cho mã nguồn rõ ràng (clean). Nếu mày nhúng tay vào những thứ dưới tiêu chuẩn này, mày không "thọ" ở đây đâu."&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Gã rảo bước.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Mã dẫn 7:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;code style="font-family: courier new;"&gt;PrimeGenerator.java (final)&lt;br /&gt;  /**&lt;br /&gt;  * This class generates prime numbers up to a user specified&lt;br /&gt;  * maximum. The algorithm used is the Sieve of Eratosthenes.&lt;br /&gt;  * Given an array of integers starting at 2: Find the first&lt;br /&gt;  * uncrossed integer, and cross out all its multiples. Repeat&lt;br /&gt;  * until there are no more multiples in the array.&lt;br /&gt;  */&lt;br /&gt;&lt;br /&gt;public class PrimeGenerator {&lt;br /&gt;   private static boolean[] crossedOut;&lt;br /&gt;   private static int[] result;&lt;br /&gt;&lt;br /&gt;   public static int[] generatePrimes(int maxValue) {&lt;br /&gt;     if (maxValue &lt; 2)&lt;br /&gt;       return new int[0];&lt;br /&gt;     else {&lt;br /&gt;       uncrossIntegersUpTo(maxValue);&lt;br /&gt;       crossOutMultiples();&lt;br /&gt;       putUncrossedIntegersIntoResult();&lt;br /&gt;       return result;&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private static void uncrossIntegersUpTo(int maxValue) {&lt;br /&gt;     crossedOut = new boolean[maxValue + 1];&lt;br /&gt;     for (int i = 2; i &lt; crossedOut.length; i++)&lt;br /&gt;       crossedOut[i] = false;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private static void crossOutMultiples() {&lt;br /&gt;     int limit = determineIterationLimit();&lt;br /&gt;     for (int i = 2; i &lt;= limit; i++)&lt;br /&gt;       if (notCrossed(i))&lt;br /&gt;         crossOutMultiplesOf(i);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private static int determineIterationLimit() {&lt;br /&gt;     // Every multiple in the array has a prime factor that is&lt;br /&gt;     // less than or equal to the sqrt of the array size, so we&lt;br /&gt;     // don't have to cross out multiples of numbers larger than&lt;br /&gt;     // that root.&lt;br /&gt;     double iterationLimit = Math.sqrt(crossedOut.length);&lt;br /&gt;     return (int) iterationLimit;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private static void crossOutMultiplesOf(int i) {&lt;br /&gt;     for (int multiple = 2*i; multiple &lt; crossedOut.length;&lt;br /&gt;       multiple += i)&lt;br /&gt;       crossedOut[multiple] = true;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private static boolean notCrossed(int i) {&lt;br /&gt;     return crossedOut[i] == false;&lt;br /&gt;   }&lt;br /&gt;   private static void putUncrossedIntegersIntoResult() {&lt;br /&gt;     result = new int[numberOfUncrossedIntegers()];&lt;br /&gt;     for (int j = 0, i = 2; i &lt; crossedOut.length; i++)&lt;br /&gt;       if (notCrossed(i))&lt;br /&gt;         result[j++] = i;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private static int numberOfUncrossedIntegers() {&lt;br /&gt;     int count = 0;&lt;br /&gt;     for (int i = 2; i &lt; crossedOut.length; i++)&lt;br /&gt;       if (notCrossed(i))&lt;br /&gt;         count++;&lt;br /&gt;&lt;br /&gt;     return count;&lt;br /&gt;   }&lt;br /&gt;}&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Mã dẫn 8:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;code style="font-family: courier new;"&gt;TestGeneratePrimes.java (final)&lt;br /&gt;import junit.framework.*;&lt;br /&gt;&lt;br /&gt;public class TestGeneratePrimes extends TestCase {&lt;br /&gt;   public static void main(String args[]) {&lt;br /&gt;     junit.swingui.TestRunner.main(&lt;br /&gt;       new String[] {"TestGeneratePrimes"});&lt;br /&gt;   }&lt;br /&gt;   public TestGeneratePrimes(String name) {&lt;br /&gt;     super(name);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void testPrimes() {&lt;br /&gt;     int[] nullArray = PrimeGenerator.generatePrimes(0);&lt;br /&gt;     assertEquals(nullArray.length, 0);&lt;br /&gt;&lt;br /&gt;     int[] minArray = PrimeGenerator.generatePrimes(2);&lt;br /&gt;     assertEquals(minArray.length, 1);&lt;br /&gt;     assertEquals(minArray[0], 2);&lt;br /&gt;&lt;br /&gt;     int[] threeArray = PrimeGenerator.generatePrimes(3);&lt;br /&gt;     assertEquals(threeArray.length, 2);&lt;br /&gt;     assertEquals(threeArray[0], 2);&lt;br /&gt;     assertEquals(threeArray[1], 3);&lt;br /&gt;     int[] centArray = PrimeGenerator.generatePrimes(100);&lt;br /&gt;     assertEquals(centArray.length, 25);&lt;br /&gt;     assertEquals(centArray[24], 97);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void testExhaustive() {&lt;br /&gt;     for (int i = 2; i&lt;500; i++)&lt;br /&gt;       verifyPrimeList(PrimeGenerator.generatePrimes(i));&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private void verifyPrimeList(int[] list) {&lt;br /&gt;     for (int i=0; i &lt; list.length; i++)&lt;br /&gt;       verifyPrime(list[i]);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private void verifyPrime(int n) {&lt;br /&gt;     for (int factor=2; factor &lt; n; factor++)&lt;br /&gt;       assert(n%factor != 0);&lt;br /&gt;   }&lt;br /&gt;}&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Quả là tai hoạ! Tôi cứ ngỡ là giải pháp nguyên thủy của tôi là thượng thặng. Chút gì đó tôi vẫn còn cảm thấy như vậy. Tôi cố phô trương tài năng của tôi nhưng tôi đoán là ông C đánh giá cao sự cộng tác và tính minh bạch hơn tài năng cá nhân.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tôi phải thú nhận rằng chương trình này dễ xem hơn lúc khởi đầu. Nó lại làm việc ngon hơn một tí nữa. Tôi khá hài lòng với kết quả và, mặc dù Jerry có thái độ cộc cằn, làm việc với gã tôi cũng thấy vui. Tôi học hỏi được rất nhiều.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Dẫu vậy, tôi thấy hơi chùn bước với chính hiệu suất của tôi. Tôi không dám nghĩ là mấy tay ở đây sẽ khoái tôi cho lắm. Tôi cũng không dám chắc đến bao bao giờ họ đánh giá tôi đủ "ngon". Sự thể sẽ khó khăn hơn tôi nghĩ nhiều lắm.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;* &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;Square root&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; hay &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;căn số&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; là cách gọi trước đây cho &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;căn bậc 2&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;, một cách gọi được dùng sau này ở VN (chú thích này dành cho những ai thắc mắc với 1 số thuật ngữ toán học xưa và nay ;))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;** &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;max prime factor&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; hay &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;thừa số nguyên tố cực đại (hoặc phân tố cực đại nguyên số)&lt;/b&gt; cũng là những thuật ngữ toán (quen dùng) trước đây. &lt;i style="font-family: verdana;"&gt;cực đại&lt;/i&gt;&lt;span style="font-family: verdana;"&gt; có thể dịch là &lt;/span&gt;&lt;i style="font-family: verdana;"&gt;tối đa&lt;/i&gt;&lt;span style="font-family: verdana;"&gt; nếu muốn (chú thích này một lần nữa dành cho những ai thắc mắc với 1 số thuật ngữ toán học xưa và nay ;))&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37459183-4327896760768254368?l=conmale.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://conmale.blogspot.com/feeds/4327896760768254368/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37459183&amp;postID=4327896760768254368' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/4327896760768254368'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/4327896760768254368'/><link rel='alternate' type='text/html' href='http://conmale.blogspot.com/2008/04/craftsman-3-clarity-and-collaboration.html' title='Craftsman 3 - Clarity and Collaboration'/><author><name>conmale</name><uri>http://www.blogger.com/profile/16598933828282382048</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/-2pIWb2iUysc/TzSYz5aVJYI/AAAAAAAAAAQ/BCWx8yVHmbU/s220/me.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37459183.post-875402053153327410</id><published>2007-07-30T10:57:00.001+10:00</published><updated>2008-04-02T11:08:06.691+11:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>Craftsman 2 - Crash Diet</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;i style="font-family: verdana;"&gt;Trong phần trước * Jerry, một tay cựu học việc, yêu cầu Alphonse, một tay học việc, viết một chương trình tạo các số nguyên tố dùng phương pháp lượt Eratosthenes (sieve of Eratosthenes). Jerry, nhận thấy Alphonse đã cài đặt toàn bộ thuật toán vào một function "khổng lồ" nên đã yêu cầu Alphonse tách nó ra theo ba khái niệm: khởi động, thực hiện (loại bỏ các số không nguyên tố) và cho ra giá trị output (đưa ra danh sách các số nguyên tố);... nhưng Alphonse không biết phải bắt đầu từ đâu... &lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Gã nhìn tôi một lúc, rõ ràng đang đợi tôi làm gì đó. Nhưng rốt cuộc gã thở dài, lắc đầu, rồi nói: "Ðể mở rộng ba khái niệm rõ hơn, tao muốn mày tách chúng ra thành ba methods riêng biệt. Ðồng thời vứt hết những cái phụ chú không cần thiết và đặt một cái tên khá hơn cho cái class. Mày làm xong những thứ đó rồi, nhớ bảo đảm là mấy cái test vẫn còn chạy được." &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Các bạn có thể thấy những điểm tôi đã làm trong &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;mã dẫn 3&lt;/b&gt;&lt;span style="font-family:verdana;"&gt;. Tôi đã đánh dấu những thay đổi bằng chữ đậm, y hệt như Martin Fowler trình bày trong cuốn Refactoring của ông ta. Tôi đổi tên của cái class thành dạng danh từ, vứt hết những phụ chú về chuyện Eratosthenes và tạo ra ba methods từ ba khái niệm trong &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;generatePrimes&lt;/b&gt;&lt;span style="font-family:verdana;"&gt; function. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Tách ra ba functions buộc tôi phải chuyển một số biến local trong cái function "khổng lồ" trước đây, thành &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;static fields&lt;/b&gt;&lt;span style="font-family:verdana;"&gt; của class. Jerry nói cách này làm rõ những biến hàm nào là local và những biến hàm nào có ảnh hưởng rộng lớn hơn. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Mã dẫn 3:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;PrimeGenerator.java, version 2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt; /**&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;  * This class generates prime numbers up to a user-specified &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;  * maximum. The algorithm used is the Sieve of Eratosthenes.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;  * Given an array of integers starting at 2: Find the first &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;  * uncrossed integer, and cross out all its multiples. Repeat &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;  * until the first uncrossed integer exceeds the square root of&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;  * the maximum value.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;  */&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt; import java.util.*;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt; public class PrimeGenerator {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;    &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;private static int s;&lt;br /&gt;  private static boolean[] f;&lt;br /&gt;  private static int[] primes;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;   public static int[] generatePrimes(int maxValue) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;     &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;if (maxValue &amp;lt; 2)&lt;br /&gt;    return new int[0];&lt;br /&gt;   else {&lt;br /&gt;    initializeSieve(maxValue);&lt;br /&gt;    sieve();&lt;br /&gt;    loadPrimes();&lt;br /&gt;    return primes; // return the primes&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;      }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;   }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;     &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;private static void loadPrimes() {{{/b}&lt;br /&gt;   int i,j;&lt;br /&gt;&lt;br /&gt;   // how many primes are there?&lt;br /&gt;   int count = 0;&lt;br /&gt;   for (i = 0; i &amp;lt; s; i++) {&lt;br /&gt;    if (f[i])&lt;br /&gt;     count++; // bump count.&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   primes = new int[count];&lt;br /&gt;&lt;br /&gt;   // move the primes into the result&lt;br /&gt;   for (i = 0, j = 0; i &amp;lt; s; i++) {&lt;br /&gt;    if (f[i])       // if prime&lt;br /&gt;     primes[j++] = i;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;private static void sieve() {{{/b}&lt;br /&gt;   int i,j;&lt;br /&gt;   for (i = 2; i &amp;lt; Math.sqrt(s) + 1; i++) {&lt;br /&gt;    // if i is uncrossed, cross out its multiples.&lt;br /&gt;    if (f[i]) {&lt;br /&gt;    for (j = 2 * i; j &amp;lt; s; j += i)&lt;br /&gt;     f[j] = false; // multiple is not prime&lt;br /&gt;     }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;private static void initializeSieve(int maxValue) {{{/b}&lt;br /&gt;   // declarations&lt;br /&gt;   s = maxValue + 1; // size of array&lt;br /&gt;   f = new boolean[s];&lt;br /&gt;&lt;br /&gt;   // initialize array to true.&lt;br /&gt;   for (int i = 0; i &amp;lt; s; i++)&lt;br /&gt;    f[i] = true;&lt;br /&gt;&lt;br /&gt;   // get rid of known non-primes&lt;br /&gt;   f[0] = f[1] = false;&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;Jerry bảo tôi mã này hơi lộn xộn, nên gã giành lấy bàn đánh và chỉ tôi cách dọn dẹp. . Mã dẫn 4 minh hoạ những gì gã đã làm. Thoạt tiên gã vứt đi cái biến hàm s trong initializeSieve và thay thế nó bằng f.length. Sau đó gã đổi tên của ba functions (theo kiểu) gã cho là có ấn tượng hơn. Cuối cùng gã sắp xếp lại cái "bộ lòng" initializeArrayOfIntegers (từ initializeSieve) để cho dễ đọc hơn một chút. Các cái test vẫn chạy nhưng thường.&lt;br /&gt;&lt;/span&gt;&lt;b style="font-family: verdana;"&gt;&lt;b&gt;&lt;b&gt;&lt;br /&gt;&lt;b&gt;Mã dẫn 4:&lt;/b&gt;&lt;br /&gt;PrimeGenerator.java, version 3 (partial)&lt;br /&gt;&lt;br /&gt; public class PrimeGenerator {&lt;br /&gt;  private static boolean[] f;&lt;br /&gt;  private static int[]  &lt;b&gt;result&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;  public static int[] generatePrimes(int maxValue) {&lt;br /&gt;   if ((&lt;b&gt;maxValue &amp;lt; 2&lt;/b&gt;)&lt;br /&gt;     return new int[0];&lt;br /&gt;   else {&lt;br /&gt;     &lt;b&gt;initializeArrayOfIntegers(maxValue);&lt;br /&gt;    crossOutMultiples();&lt;br /&gt;    putUncrossedIntegersIntoResult();&lt;br /&gt;    return result;&lt;/b&gt;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private static void&lt;br /&gt;initializeArrayOfIntegers(int maxValue) {&lt;br /&gt;   f = new boolean[an[&lt;b&gt;maxValue + 1&lt;/b&gt;];&lt;br /&gt;   f[0] = f[1] = false; &lt;b&gt;//neither primes nor multiples.&lt;/b&gt;&lt;br /&gt;   for (int i = 2; i &amp;lt; &lt;b&gt;f.length&lt;/b&gt;; i++)&lt;br /&gt;    f[i] = true; &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;Tôi phải công nhận mã này rõ hơn một chút. Trước giờ tôi nghĩ tạo functions có tên sinh động là phí thời giờ , nhưng những chỉnh đổi của gã quả thật làm cho mã nguồn dễ đọc hơn.&lt;br /&gt;&lt;br /&gt;Tiếp theo Jerry trỏ vào  crossOutMultiples, nói là gã nghĩ cụm if(f[i] == true) có thể làm cho dễ đọc hơn nữa. Tôi nghĩ đến điểm này chừng một phút. Ý định của các cụm này dùng để kiểm tra xem i không bị loại trừ; thế là tôi đổi tên của f thành unCrossed.&lt;br /&gt;&lt;br /&gt;Jerry nói mã này coi được hơn nhưng vẫn chưa vừa ý vì nó dẫn đến khả năng phủ định đôi (double negative) như unCrossed[i] = false. Bởi thế gã đổi tên của dãy số thành dãy isCrossed. Các cái test vẫn chạy được.&lt;br /&gt;&lt;br /&gt;Jerry bỏ qua phần khởi động : gán cho isCrossed[0] và isCrossed[1] giá trị true . Gã nói, chúng ta có thể giả sử không chỗ nào của thuật toán dùng dãy isCrossed với với chỉ số nhỏ hơn 2 . Các cái test vẫn chạy được.&lt;br /&gt;&lt;br /&gt;Jerry tách phần lặp bên trong (inner loop) của crossOutMultiples function và gọi nó là crossOutMultipleOf. Gã bảo rằng các cụm tương tự như if (isCrossed[i] == false) dễ nhầm lẫn nên gã tạo ra function có tên notCrossed và thay cụm if thành if (notCrossed(i)). Kết tiếp gã chạy thử mấy cái test lại.&lt;br /&gt;&lt;br /&gt;Sau đó Jerry hỏi tôi ý nghĩa của phần số căn đó là gì. Tôi tốn một ít thời giờ viết phụ chú giải thích tại sao cần phải lặp lại cho đến phần số căn của chiều dài dãy số. Tôi cố tranh đua với Jerry bằng cách tách phần tính toán thành một function, nơi tôi có thể đưa vào phần phụ giải. Trong khi viết ghi chú tôi nhận ra rằng căn số là thừa số nguyên tố cực đại của một số bất kỳ trong một dãy số. Bởi thế để ứng phó, tôi chọn cách gọi đó (maxValue) cho các biến, hàm. Cuối cùng tôi bảo đảm các tests vẫn chạy được. Kết quả của các thay đổi trong mã dẫn 5.&lt;/span&gt;&lt;b style="font-family: verdana;"&gt;&lt;b&gt;&lt;b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Mã dẫn 5:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;PrimeGenerator.java version 4 (partial)&lt;br /&gt; public class PrimeGenerator {&lt;br /&gt;  private static boolean[] isCrossed;&lt;br /&gt;  private static int[] result;&lt;br /&gt;&lt;br /&gt;  public static int[] generatePrimes(int maxValue) {&lt;br /&gt;   if (maxValue &amp;lt; 2)&lt;br /&gt;    return new int[0];&lt;br /&gt;   else {&lt;br /&gt;    initializeArrayOfIntegers(maxValue);&lt;br /&gt;    crossOutMultiples();&lt;br /&gt;    putUncrossedIntegersIntoResult();&lt;br /&gt;    return result;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private static void&lt;br /&gt;  initializeArrayOfIntegers(int maxValue) {&lt;br /&gt;   isCrossed = new boolean[maxValue + 1];&lt;br /&gt;   for (int i = 2; i &amp;lt; isCrossed.length; i++)&lt;br /&gt;    isCrossed[i] = false;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private static void crossOutMultiples() {&lt;br /&gt;   int maxPrimeFactor = calcMaxPrimeFactor();&lt;br /&gt;   for (int i = 2; i &amp;lt;= maxPrimeFactor; i++)&lt;br /&gt;    if (notCrossed(i))&lt;br /&gt;     crossOutMultiplesOf(i);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private static int calcMaxPrimeFactor() {&lt;br /&gt;   // We cross out all multiples of primes. Thus, all crossed&lt;br /&gt;   // out multiples have p and q for factors. If p &amp;gt; sqrt of the&lt;br /&gt;   // size of the array, then q will never be greater than 1.&lt;br /&gt;   // Thus p is the largest prime factor in the array, and is&lt;br /&gt;   // also the iteration limit.&lt;br /&gt;   double maxPrimeFactor =  Math.sqrt(isCrossed.length) + 1;&lt;br /&gt;   return (int) maxPrimeFactor;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private static void crossOutMultiplesOf(int i) {&lt;br /&gt;   for (int multiple = 2*i; multiple &amp;lt; isCrossed.length;&lt;br /&gt;        multiple += i)&lt;br /&gt;    isCrossed[multiple] = true;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private static boolean notCrossed(int i) {&lt;br /&gt;   return isCrossed[i] == false;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;Tôi bắt đầu nắm bắt được vấn đề nên liền xét lại method xét lại method putUncrossedIntegersIntoResult. Tôi thấy rằng method này có hai phần. Phần thứ nhất đếm các số nguyên không bị loại trong dãy số, và tạo nên dãy kết quả (bằng chiều dài của dãy số). Phần thứ nhì dời các số nguyên không bị loại vào dãy kết quả này. Bởi thế, như bạn thấy trong mã dẫn 6, tôi tách phần thứ nhất ra để hình thành function cho chính nó và dọp dẹp lặt vặt đôi chút. Các tests vẫn chạy được. Jerry chỉ thoáng gật đầu. Gã có thật sự khoái những điều tôi đã thực hiện không?&lt;/span&gt;&lt;b style="font-family: verdana;"&gt;&lt;b&gt;&lt;b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Mã dẫn 6:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;PrimeGenerator.java, version 5 (partial).&lt;br /&gt; private static void putUncrossedIntegersIntoResult() {&lt;br /&gt;   result = new int[numberOfUncrossedIntegers()];&lt;br /&gt;   for (int j = 0, i = 2; i &amp;lt; isCrossed.length; i++)&lt;br /&gt;    if (notCrossed(i))&lt;br /&gt;     result[j++] = i;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private static int numberOfUncrossedIntegers() {&lt;br /&gt;   int count = 0;&lt;br /&gt;   for (int i = 2; i &amp;lt; isCrossed.length; i++)&lt;br /&gt;    if (notCrossed(i))&lt;br /&gt;     count++;&lt;br /&gt;     return count;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;&lt;br /&gt;* Trong nguyên bản là "In the last month's column..." nhưng ở đây tạm dịch thoáng ra là "trong phần trước" cho phù hợp với tinh thần các bài craftsman được post lên (không theo tháng mà theo... tùy hứng của người dịch)&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37459183-875402053153327410?l=conmale.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://conmale.blogspot.com/feeds/875402053153327410/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37459183&amp;postID=875402053153327410' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/875402053153327410'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/875402053153327410'/><link rel='alternate' type='text/html' href='http://conmale.blogspot.com/2007/07/craftsman-2-crash-diet.html' title='Craftsman 2 - Crash Diet'/><author><name>conmale</name><uri>http://www.blogger.com/profile/16598933828282382048</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/-2pIWb2iUysc/TzSYz5aVJYI/AAAAAAAAAAQ/BCWx8yVHmbU/s220/me.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37459183.post-8909076849961218417</id><published>2007-07-18T08:47:00.000+10:00</published><updated>2007-07-18T09:06:59.511+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>Craftsman 1 - Opening Disaster</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;The crafsman One.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Robert C. Martin&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;13 Tháng 2, 2002&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Bài viết này lược trích từ chương Principles, Patterns and Practices trong cuốn Agile Software Development của Robert C. Martin, nhà xuất bản Prentice Hall, 2002.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Nhật ký thân mến,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;13 tháng 2, 2002.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Hôm nay đúng là một ngày xui xẻo - Tôi làm hỏng cả chuyện. Tôi rất muốn gây ấn tượng với các ngài "cựu học việc" ở đây nhưng rút cuộc chỉ làm rối tung cả lên.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Ðó là ngày đầu tiên tôi được một chân học việc với ông C. Tôi quả là may mắn có được chân học việc này. Ông C là một tay trùm lớp lang trong vấn đề phát triển phần mềm. Ðấu để giành được chân việc này đúng là nẩy lửa. Các tay học việc của ông C thường trở nên các tay "cựu học việc" sáng giá. Ðiều này có nghĩa được làm việc với ông C có giá trị rõ ràng.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Tôi cứ ngỡ là hôm nay tôi sẽ được gặp ông ta nhưng thay vì đó tôi bị một gã "cựu học việc" níu tôi qua một bên. Gã bảo ông C luôn luôn dẫn các tay học việc đi xuyên qua phần định hướng trong những ngày đầu. Gã nói ông C nhất quyết cho rằng phần thực tập định hướng là thiết thực với các tay học việc và nó dẫn đến mức chất lượng mã nguồn mà ông ta ta dự tưởng.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Tôi náo nức kinh khủng. Ðây là một cơ hội cho họ thấy tôi là một tay lập trình "ngon" cỡ nào. Thế là tôi bảo Jerry tôi không chờ được nữa. Gã đáp lại sự náo nức của tôi bằng cách bảo tôi thử viết một chương trình đơn giản cho gã. Gã muốn tôi dùng "Sieve of Eratosthenes" để tính các số nguyên tố. Gã còn bảo tôi phải chuẩn bị xong chương trình bao gồm trọn bộ các "unit tests" sẵn sàng để "chấm" sau buổi ăn trưa.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Thật là khoái! Tôi có gần 4 tiếng đồng hồ để "xào nấu" một chương trình giống như Sieve. Tôi quyết tâm thực hiện công tác này một cách hết sức có ấn tượng. &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;Mã dẫn 1&lt;/b&gt;&lt;span style="font-family:verdana;"&gt; đưa ra những gì tôi đã viết. Tôi nắm chắc là chương trình của tôi được chú thích cẩn thận và trình bày gọn gàng.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Mã dẫn 1:&lt;/b&gt;&lt;br /&gt;&lt;code style="font-family: courier new;"&gt;&lt;/code&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;/**&lt;br /&gt;* This class generates prime numbers up to a user-specified maximum.&lt;br /&gt;* The algorithm used is the Sieve of Eratosthenes.&lt;br /&gt;* &amp;lt;p&amp;gt;&lt;br /&gt;* Eratosthenes of Cyrene, b. c. 276 BC, Cyrene, Libya; d. c. 194 BC, Alexandria. He was&lt;br /&gt;* the first man to calculate the circumference of the Earth, and was also&lt;br /&gt;* known for working on calendars with leap years and running the library at&lt;br /&gt;* Alexandria.&amp;lt;/p&amp;gt;&lt;br /&gt;*&lt;br /&gt;* The algorithm is quite simple: Given an array of integers starting at 2,&lt;br /&gt;* cross out all multiples of 2. Find the next uncrossed integer, and cross&lt;br /&gt;* out all of its multiples. Repeat until you have passed the square root of&lt;br /&gt;* the maximum value.&lt;br /&gt;*&lt;br /&gt;* @authorAlphonse, @version 13 Feb 2002 atp&lt;br /&gt;*/&lt;br /&gt;import java.util.*;&lt;br /&gt;&lt;br /&gt;public class GeneratePrimes {&lt;br /&gt;/**&lt;br /&gt;* @param maxValue is the generation limit.&lt;br /&gt;*/&lt;br /&gt;public static int[] generatePrimes(int maxValue) {&lt;br /&gt;   if (maxValue &amp;gt;= 2) { // the only valid case&lt;br /&gt;   // declarations&lt;br /&gt;   int s = maxValue + 1; // size of array&lt;br /&gt;   boolean[] f = new boolean[s];&lt;br /&gt;   int i;&lt;br /&gt;&lt;br /&gt;   // initialize array to true.&lt;br /&gt;   for (i = 0; i &amp;lt; s; i++)&lt;br /&gt;       f[i] = true;&lt;br /&gt;&lt;br /&gt;   // get rid of known non-primes.&lt;br /&gt;   f[0] = f[1] = false;&lt;br /&gt; &lt;br /&gt;   // sieve&lt;br /&gt;   int j;&lt;br /&gt;   for (i = 2; i &amp;lt; Math.sqrt(s) + 1; i++) {&lt;br /&gt;   if (f[i]) { // if i is uncrossed, cross its multiples.&lt;br /&gt;       for (j = 2 * i; j &amp;lt; s; j += i)&lt;br /&gt;       f[j] = false; // multiple is not prime&lt;br /&gt;   }&lt;br /&gt;  }&lt;/blockquote&gt;&lt;br /&gt;&lt;blockquote&gt;        // how many primes are there?&lt;br /&gt;      int count = 0;&lt;br /&gt;      for (i = 0; i &amp;lt; s; i++) {&lt;br /&gt;   if (f[i])&lt;br /&gt;       count++; // bump count.&lt;br /&gt;   }&lt;br /&gt;      int[] primes = new int[count]; &lt;br /&gt;&lt;br /&gt;      // move the primes into the result.&lt;br /&gt;      for (i = 0, j = 0; i &amp;lt; s; i++) {&lt;br /&gt;if (f[i]) // if prime &lt;br /&gt;   primes[j++] = i;&lt;br /&gt;      }   &lt;/blockquote&gt;&lt;blockquote&gt;        return primes; // return the primes.&lt;br /&gt;   } else // maxValue &amp;lt; 2&lt;br /&gt;       return new int[0];  // return null array if bad input.&lt;br /&gt;   }&lt;br /&gt;}&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Sau đó tôi viết một cái "unit test" cho GeneratePrimes. Xem ở &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;mã dẫn 2&lt;/b&gt;&lt;span style="font-family:verdana;"&gt;. Ðoạn mã này dùng JUnit framework như Jerry đã chỉ dẫn. Nó dùng tính chất hướng thống kê; kiểm tra xem cái "generator" có thể tạo ra các số nguyên tố tới 0, 2, 3 và 100. Trong trường hợp thứ nhất hẳn không có số nguyên tố nào cả. Trong trường hợp thứ nhì hẳn phải có một số nguyên tố và nó phải là số 2. Trường hợp thứ ba phải có hai số nguyên tố và chúng phải là số 2 và 3. Trường hợp cuối phải là 25 số nguyên tố và số cuối phải là 97. Nếu các bước kiểm tra đều đúng, tôi giả định là cái "generator" làm việc đúng. Tôi e rằng khó có thể tin cậy tuyệt đối cách ở trên, nhưng tôi không nghĩ ra được một trường hợp nào một "function" có thể bị hỏng mà các bước kiểm tra đều đúng.  &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Mã dẫn 2:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;code style="font-family: courier new;"&gt;&lt;/code&gt;&lt;blockquote&gt;import junit.framework.*;&lt;br /&gt;import java.util.*;&lt;br /&gt;&lt;br /&gt;public class TestGeneratePrimes extends TestCase {&lt;br /&gt;public static void main(String args[]) {&lt;br /&gt;  Junit.swingui.TestRunner.main(&lt;br /&gt;  new String[] {"TestGeneratePrimes"});&lt;br /&gt;}&lt;br /&gt;public TestGeneratePrimes(String name) {&lt;br /&gt;   super(name);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void testPrimes() {&lt;br /&gt;   int[] nullArray = GeneratePrimes.generatePrimes(0);&lt;br /&gt;   assertEquals(nullArray.length, 0);&lt;br /&gt;&lt;br /&gt;   int[] minArray = GeneratePrimes.generatePrimes(2);&lt;br /&gt;   assertEquals(minArray.length, 1);&lt;br /&gt;   assertEquals(minArray[0], 2);&lt;br /&gt;&lt;br /&gt;   int[] threeArray = GeneratePrimes.generatePrimes(3);&lt;br /&gt;   assertEquals(threeArray.length, 2);&lt;br /&gt;   assertEquals(threeArray[0], 2);&lt;br /&gt;   assertEquals(threeArray[1], 3);&lt;br /&gt;&lt;br /&gt;   int[] centArray = GeneratePrimes.generatePrimes(100);&lt;br /&gt;   assertEquals(centArray.length, 25);&lt;br /&gt;   assertEquals(centArray[24], 97);&lt;br /&gt;   }&lt;br /&gt;}&lt;/blockquote&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Tôi mất khoảng một giờ đồng hồ để làm những bước trên chạy được. Jerry không muốn gặp tôi cho đến sau buổi ăn trưa, bởi thế, tôi dành trọn bộ thời gian còn lại đọc cuốn Design Patterns mà Jerry đưa cho tôi.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Sau buổi ăn trưa, tôi ghé văn phòng của Jerry và cho gã biết tôi đã thực hiện xong chương trình. Gã nhìn tôi và với một nụ cười khó tả, hắn nói: &lt;span style="font-style: italic;"&gt;"Ðược lắm, hãy xem thử nó thế nào."&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Gã dẫn tôi và phòng thí nghiệm và cho tôi ngồi trước một máy. Gã ngồi bên cạnh tôi và yêu cầu tôi đưa chương trình của tôi vào máy này. Thế là tôi chuyển mã nguồn từ máy laptop của tôi lên.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Jerry xem xét hai mã nguồn chừng năm phút rồi gã lắc đầu và bảo: &lt;span style="font-style: italic;"&gt;"Mày không thể đưa những cái này cho ông C xem được! Nếu tao để ổng xem mấy cái này, ổng sẽ đuổi cổ cả tao lẫn mày. Ông ấy không phải là người kiên nhẫn đâu."&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Tôi đánh thót một phát nhưng cố giữ bình tĩnh và hỏi gã: &lt;span style="font-style: italic;"&gt;"Chớ nó sai chỗ nào?"&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Jerry thở dài và nói: &lt;span style="font-style: italic;"&gt;"Tụi mình nên đi xuyên qua mã nguồn này với nhau." "Tao sẽ chỉ cho mày từng điểm một cách ông C muốn thực hiện nó như thế nào."&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;&lt;span style="font-style: italic;"&gt;"Quá rõ ràng"&lt;/span&gt;, gã tiếp tục, &lt;span style="font-style: italic;"&gt;"cái main function muốn làm ra ba cái functions riêng biệt. Cái thứ nhất khởi tạo tất cả các biến hàm và thiết lập cái "sieve". Cái thứ nhì thực sự thi hành cái "sieve" và cái thứ ba tải kết quả của "sieve" vào một dãy số nguyên tố."&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Tôi nhận ra được ý gã muốn nói gì. Có ba khái niệm chôn trong cái function đó. Tuy vậy, tôi không biết gã muốn tôi phải làm gì với nó.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Gã nhìn tôi một lúc, rõ ràng đang đợi tôi phản ứng sao đó. Nhưng rốt cuộc gã thở dài, lắc đầu và....&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37459183-8909076849961218417?l=conmale.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://conmale.blogspot.com/feeds/8909076849961218417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37459183&amp;postID=8909076849961218417' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/8909076849961218417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/8909076849961218417'/><link rel='alternate' type='text/html' href='http://conmale.blogspot.com/2007/07/craftsman-1-opening-disaster.html' title='Craftsman 1 - Opening Disaster'/><author><name>conmale</name><uri>http://www.blogger.com/profile/16598933828282382048</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/-2pIWb2iUysc/TzSYz5aVJYI/AAAAAAAAAAQ/BCWx8yVHmbU/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37459183.post-8032581914263665694</id><published>2007-07-17T08:28:00.000+10:00</published><updated>2007-07-17T08:33:36.924+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Qmail as a Mail Gateway - Phần cuối</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;5.  Ðiều chỉnh sau khi cài đặt&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Trước đây, khi Internet còn giới hạn (chỉ phổ biến giữa các trường đại học và các nhóm nghiên cứu và rất ít người dùng bình thường), mail là một phương tiện tuyệt vời để liên lạc và trao đổi. Tính thương mại hoá hầu như chưa có cho đến khi loạt “SPAM” đầu tiên xuất hiện đã biến Internet mail trở nên một vấn đề gần như nan giải đối với các loạt mail “vô chủ” chuyên để quảng cáo.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Có hai trường hợp thường xảy ra trong vấn nạn “SPAM” đó là:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Bị biến thành phương tiện để “SPAM” những nạn nhân khác nếu mail server không được điều chỉnh và kiểm soát đúng mức (bị relay).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Bị “SPAM” (bom thư).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;5.1 Chiến thuật relaying điện thư (để không biến mail server của mình trở thành phương tiện để “SPAM”&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;5.1.1 Tại sao cần relay?&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Như đã đề cập đến trong phần 3.5 (Bộ quản trị SMTP Access Control), có những trường hợp bạn cần cho phép mail gateway của mình relay mail vì lý do nào đó (chuyển nhận mail dùng cho công ty bạn hoặc mail server của bạn dùng để relay mail cho nhiều domain khác nhau như một mail server của ISP). Nói một cách ngắn gọn, khả năng “mail relaying”của một mail server A là khả năng tiếp nhận mail từ host X và chuyển gởi mail này đến host Y hoặc những host nào đó trong chế độ định sẵn mà mail server phải đảm nhiệm.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;5.1.2 Chuyện gì xảy ra nếu không relay?&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Nếu mail gateway của bạn chỉ dành phục vụ cho một domain riêng của bạn thì vấn đề relay không còn cần thiết nữa và quyết định hoàn toàn không relay là cách an toàn nhất để ngăn ngừa trường hợp mail gateway của bạn bị biến thành một phương tiện để SPAM.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;  &lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;5.1.3 Cho phép relaying theo lựa chọn&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Trong phần 3.5 đã đi sâu vào chi tiết sắp xếp cho phép relay một cách chọn lọc, một trong những variables cần phải chú tâm đến là: &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;allow,RELAYCLIENT&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Nên xem xét một cách &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;kỹ lưỡng&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; các giá trị “RELAYCLIENT” để nắm chắc bạn đã không cho phép một “client” nào đó được phép relay vì sơ ý.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;5.1.4 Thử nghiệm relaying bằng tcprulescheck&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Trong nhóm “ucspi-tcp” có một chương trình gọi là &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;tcprulescheck&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; cho phép bạn kiểm tra các “luật” relay trước khi ứng dụng Qmail như một mail relay server thực sự. &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;tcprulescheck&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; dùng 2 variables của môi trường để kiểm tra các “luật” relay, đó là: &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;TCPREMOTEIP&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;TCPREMOTEHOST&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Bạn có thể thay đổi các variables này cho quy trình kiểm tra.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Sau đây là một ví dụ đơn giản quy trình kiểm tra các “luật” relay bằng &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;tcprulescheck&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Giả sử chúng ta dùng ví dụ &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;qmail-rules.txt&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; từ phần 3.5. &lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;127.:allow,RELAYCLIENT=””&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;192.168.1.:allow,RELAYCLIENT=””&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;10.10.10.50:allow,RELAYCLIENT=””&lt;/span&gt;&lt;br /&gt;&lt;a style="font-family: courier new;" href="mailto:spamboy@spamhouse.com"&gt;spamboy@spamhouse.com&lt;/a&gt;&lt;span style="font-family: courier new;"&gt;:deny&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;badhost.net:deny&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;.:deny&lt;/span&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Chúng ta thử “cat” qmail-rules.txt và “pipe” nó xuyên qua chương trình tcprules để tạo ra hash của các rules thuộc “qmail-rules.txt” (nên nhớ smtpd daemon dùng hash của qmail-rules.txt, đó là hồ sơ &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;tcp.smtp.cdb&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;, nó không bao giờ dùng nguyên bản cleartext qmail-rules.txt):&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: courier new;"&gt;# cat /etc/smtprules/qmail-rules.txt | tcprules /etc/tcp.smtp.cdb&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Hash của các rules được chứa trong hồ sơ &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;tcp.smtp.cdb&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và chúng ta sẽ dùng hồ sơ này để kiểm tra các “luật” relay.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;a.&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Lệnh &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;$ tcprulescheck /etc/tcp.smtp.cdb&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; sẽ cho kết quả:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;rule:&lt;br /&gt;deny connection&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Trường hợp ở trên tcprulescheck dùng giá trị mặc định (default) của “qmail-rules.txt” đó là &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;.:deny&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Bất cứ truy cập nào vào mail relay server của bạn, đầu tiên nó sẽ dùng giá trị mặc định để “deny” trước và sau đó dựa trên IP hoặc hostname của nơi gởi mail mà định đoạt “số phận” của mail này.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;b.&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Thử lệnh trên một lần nữa trước khi chỉnh variable TCPREMOTEIP là 10.10.10.50 như đã cho phép trong “qmail-rules.txt” ở trên:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ TCPREMOTEIP=10.10.10.50 ; export TCPREMOTEIP&lt;br /&gt;$ tcprulescheck /etc/tcp.smtp.cdb&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; sẽ cho kết quả:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: courier new;"&gt;rule: 10.10.10.50:&lt;br /&gt;set environment variable RELAYCLIENT=&lt;br /&gt;allow connection&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ở trên cho thấy qmail chấp nhận TCPREMOTEIP là 10.10.10.50 là vì IP này đã thuộc trong danh sách qmail-rules.txt và được thiết lập ở chế độ &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;allow,RELAYCLIENT&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; nên tcprulescheck trả lời: &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;allow connection&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;c.&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Thử lệnh trên với TCPREMOTEIP mang giá trị khác, giả sử như &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;badhost.net&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; có IP là 172.173.174.175 (được thiết lập ở chế độ deny trong qmail-rules.txt)&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ TCPREMOTEIP=172.173.174.175 ; export TCPREMOTEIP&lt;br /&gt;$ tcprulescheck /etc/tcp.smtp.cdb&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; sẽ cho kết quả:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;&lt;span style="font-family: courier new;"&gt;rule: badhost.net:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;deny connection&lt;/span&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ở trên cho thấy Qmail từ chối không nhận mail muốn được chuyển nhận đến server 172.173.174.175 (IP của badhost.com trong ví dụ này) vì địa chỉ này được ấn định là &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;deny&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Cứ như vậy, bạn đi xuyên qua mỗi “rule” trong qmail-rules.txt để kiểm tra chức năng relay của các rules.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;5.1.5 Thử nghiệm relaying bằng “telnet”&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Phương pháp dùng “telnet” để truy cập vào một mail server ở port 25 (SMTP port) có lẽ là một phương pháp cổ điển và phổ biến nhất để kiểm tra tính năng “relay” của nó. Ðây cũng là một trong những phương pháp các tay chuyên tìm kiếm “open relay” để có thể SPAM, tất nhiên không bằng cách “telnet” từng mail server mà bằng cách “tự động hoá” qua một dạng scripting nào đó để có thể đi xuyên qua hàng loạt mail server trong một khoảng thời gian ngắn.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ở đây tôi sẽ đưa ra hai ví dụ đơn giản để kiểm tra tính năng “relay” của mail server của bạn. Ðòi hỏi đơn giản chỉ cần có chương trình “telnet” trong máy. Tính năng “relay” dựa trên hồ sơ “rcpthosts” (trong phần 4.2.7) có các giá trị như sau:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;mail.mydomain.com&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;exchange1.mydomain.com&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;exchange2.mydomain.com&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;mydomain.net&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;mail.myfriend.com &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Khởi động telnet trên một command prompt (Windows hoặc *nix tùy chọn). Giả sử mail gateway server của tôi có địa chỉ là 192.168.1.200 với hostname là mail.mydomain.com chẳng hạn, tôi sẽ làm các bước như sau:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;1   &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;telnet 192.168.1.200 25&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;2   &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;220 My company mail server - Welcome ESMTP&lt;/b&gt;&lt;span style="font-family: courier new;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;3   &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;HELO&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;4   &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;250  My company mail server – Welcome&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;5   &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;MAIL FROM: &amp;lt;&lt;a href="mailto:spamboy@spamhouse.com"&gt;spamboy@spamhouse.com&lt;/a&gt;&amp;gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;6   &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;250 ok&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;7   &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;RCPT TO: &amp;lt;&lt;a href="mailto:reciepient@someonecompany.com"&gt;reciepient@someonecompany.com&lt;/a&gt;&amp;gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;8   &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Dòng 1:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Dùng telnet với các thông số là IP 192.168.1.200 và SMTP port 25.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Dòng 2:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Nếu mail server của tôi đang hoạt động bình thường, tôi sẽ nhận được lời chào (bạn còn nhớ hồ sơ “smtpgreeting” trong phần 4.2.8? đây chính là lời chào lấy từ hồ sơ “smtpgreeting” này).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Dòng 3:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Tôi thử lệnh HELO, một lệnh căn bản của SMTP.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Dòng 4:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Mail server của tôi sẽ trả lời với thông điệp lấy từ “smtpgreeting”.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Dòng 5:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Tôi “mạo danh” là &lt;/span&gt;&lt;a style="font-family: verdana;" href="mailto:spamboy@spamhouse.com"&gt;spamboy@spamhouse.com&lt;/a&gt;&lt;span style="font-family: verdana;"&gt; qua lệnh &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;MAIL FROM:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Dòng 6:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Mail server trả lời &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;250 ok&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; bởi vì tôi chưa cho mail server của tôi biết là người nhận sẽ là ai và người nhận thuộc domain nào. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Dòng 7:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Tôi dùng lệnh &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;RCPT TO:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và cho mail server biết người nhận là &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;reciepient&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; thuộc domain &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;someonecompany.com&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;; một domain không hề có trong rcpthosts.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Dòng 8:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Qmail sẽ từ chối ngay lập tức.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Hãy thử kiểm tra relaying bằng telnet dùng các giá trị người nhận thuộc domain có trong hồ sơ “rcpthosts”. Quy trình này tương tự như sau:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;1    &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;telnet 192.168.1.200 25&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;2    &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;220 My company mail server - Welcome ESMTP&lt;/b&gt;&lt;span style="font-family: courier new;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;3    &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;HELO&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;4    &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;250  My company mail server – Welcome&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;5    &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;MAIL FROM: &amp;lt;&lt;a href="mailto:spamboy@spamhouse.com"&gt;spamboy@spamhouse.com&lt;/a&gt;&amp;gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;6    &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;250 ok&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;7    &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;RCPT TO: &amp;lt;&lt;a href="mailto:someone@mydomain.net"&gt;someone@mydomain.net&lt;/a&gt;&amp;gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;8    &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;250 ok&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;9    &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;DATA&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;10  &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;354 go ahead&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;11   &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;From: &lt;a href="mailto:spamboy@spamhouse.com"&gt;spamboy@spamhouse.com&lt;/a&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;12   &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;To: &lt;a href="mailto:someone@mydomain.net"&gt;someone@mydomain.net&lt;/a&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;13   &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;Subject: a relay test&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;14   &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;This is only a test for open relay&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;15   &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;.&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;16   &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;250 ok 1041050865 qp 12150&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;17   &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;QUIT&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;18   &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;221 My company mail server – Welcome&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;19   &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;20   &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;Connection to host lost.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Dòng 1 đến dòng 6:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; tương tự như ví dụ ở trên&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Dòng 7:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Lệnh &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;RCPT TO:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; gởi đến người nhận thuộc domain &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;mydomain.net&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;, domain này có trong danh sách &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;rcpthosts&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Dòng 8:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Mail server tiếp nhận và trả lời với SMTP code 250. Sở dĩ mail server tiếp nhận trong trường hợp này là vì domain &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;mydomain.net&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; hiện diện trong rcpthosts&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Dòng 9:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Lệnh &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;DATA&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; để báo với mail server dự định gởi thông điệp&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Dòng 10:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Mail server tiếp nhận và trả lời với SMTP code 354&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Dòng 11 đến dòng 13:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Các “message header” &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;From&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;, &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;To&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;Subject&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; thông thường để mail client có thể hiển thị những thông tin này&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Dòng 14:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Nội dung của thông điệp. Nội dung này có thể trải ra thành nhiều dòng nếu cần&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Dòng 15:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Dấu chấm (.) để kết thúc thông điệp&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Dòng 16:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Mail server trả lời kết thúc một “xuất” gởi thông điệp&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Dòng 17:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Lệnh QUIT dùng để dừng truy cập đến mail server bằng telnet&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Dòng 18:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Mail server trả lời với SMTP code 221, ngưng truy cập vào mail server thành công&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Dòng 19 và dòng 20:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Dòng trống trên console và thông điệp telnet báo không còn truy cập đến mail server nữa.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ở trên bạn thấy người gởi “&lt;/span&gt;&lt;a style="font-family: verdana;" href="mailto:spamboy@spamhouse.com"&gt;spamboy@spamhouse.com&lt;/a&gt;&lt;span style="font-family: verdana;"&gt;” vẫn có thể gởi mail đến “&lt;/span&gt;&lt;a style="font-family: verdana;" href="mailto:someone@mydomain.net"&gt;someone@mydomain.net&lt;/a&gt;&lt;span style="font-family: verdana;"&gt;” vì domain mydomain.net hiện diện trong hồ sơ “rpcthost”. Nếu trong hồ sơ “qmail-rules.txt” có dữ kiện dùng để “deny” người gởi này, chắc chắn mail ở trên không thể đi vào mail server của bạn được. Ví dụ trên một phần nào minh hoạ quan hệ giữa “qmail-rules.txt” và “rcpthosts” trên phương diện chống relay và chống spam.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Qua hai phần thử nghiệm 5.1.4 và 5.1.5 chúng ta có thể rút tỉa được một số điểm quan trọng như sau:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Hồ sơ “qmail-rules.txt” dùng để xác định các &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;host&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; được phép relay và được phép dùng mail gateway để chuyển mail. Nó còn có trách nhiệm giúp Qmail quyết định mail &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;đến&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;đi&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; từ các host nào sẽ có số phận ra sao. Ðịnh nghĩa &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;ÐẾN&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;ÐI&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; ở đây có nghĩa là mail &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;đi từ bên ngoài domain của bạn&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; hoặc &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;bên ngoài những domain bạn cho phép relay&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Ngoài hồ sơ “badmailfrom” (xem lại trong phần 4.2.6), “qmail-rules.txt” là nơi để xác định những domains, hosts và các e-mail bạn không muốn tiếp nhận (qua phương thức &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;:deny&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;). &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Hồ sơ “rpcthost” dùng để xác định các &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;domain&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; nào được Qmail relay server giao chuyển mail. Ðiều này có nghĩa, Qmail dựa trên những dữ liệu của “rpcthosts” để tiếp nhận mail từ một nơi nào đó đến một mail server nào mà nó đã chịu trách nhiệm relay. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;5.2 Chiến thuật chống bom thư với Qmail&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Các bước 5.14 và 5.1.5 ở trên dùng để kiểm tra lại những lỗ hổng “relay” trên bình diện mail gateway được dùng để relay (hoặc mail gateway được làm phương tiện để spam các hòm thư). Hồ sơ “qmail-rules.txt” có thể dùng để quy định những e-mail, domains hoặc một chuỗi địa chỉ bạn không muốn nhận mail. Ðây là có thể là một cách chống bom thư nhưng thiếu tính “tự động hoá” vì bạn phải thường xuyên theo dõi, cập nhật các dữ kiện trong hồ sơ này. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ðể nâng cao khả năng chống bom mail với tính “tự động hoá”, trong phần này chúng ta bàn về vấn đề dùng các RBL (realtime black list) database phối hợp với “qmail-rules.txt” để chống bom thư một cách hữu hiệu hơn.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Trong phần 3.4.2 trước đây, chúng ta nói đến chương trình “tcpserver” được sử dụng trong script “run” cho &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;qmail-smtpd&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Hãy xem lại đoạn script chạy “tcpserver” của phần 3.4.2:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;#!/bin/sh&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;# concurincoming is not standard qmail control file&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;# it is created manually to specify the allowed concurrent incoming messages&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;#&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;QMAILDUID=`id -u qmaild`&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;NOFILESGID=`id -g qmaild`&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;MAXSMTPD=`cat /var/qmail/control/concurincoming`&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;if [ -z "$QMAILDUID" -o -z "$NOFILESGID" -o -z "$MAXSMTPD" ]; then&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;        echo QMAILDUID, NOFILESGID, or MAXSMTPD is not set in&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;        echo /var/qmail/supervise/qmail-smtpd/run&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    echo “Have you set qmaild UID &amp; qmaild GID yet?”&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;        exit 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;     fi&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: courier new;"&gt;exec /usr/local/bin/softlimit -m 6291456 \&lt;br /&gt;    /usr/local/bin/tcpserver -v -p -x /etc/tcp.smtp.cdb -c "$MAXSMTPD" \&lt;br /&gt;        -u "$QMAILDUID" -g "$NOFILESGID" 0 smtp /var/qmail/bin/qmail-smtpd 2&amp;gt;&amp;1&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ở trên &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;tcpserver&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; chỉ dùng “tcp.smtp.cdb”, hồ sơ này được “hash” từ “qmail-rules.txt” để chống relay và bom thư theo dạng đơn giản. Cũng với cơ chế này, chúng ta có thể dùng “rblsmtpd” cùng với “tcpserver” để báo cho qmail server biết nó có trách nhiệm phải kiểm tra các mail đi xuyên qua mail gateway có thuộc dạng “SPAM” trước khi được chấp nhận. Phương thức kiểm tra bằng cách đối chiếu dữ kiện ở một trong những RBL servers. Có một số RBL database miễn phí trên internet. Có hai RBL cá nhân tôi dùng là: &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;ordb.org&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;osirusoft.com&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; (bạn có thể đọc thêm một số tin tức về RBL từ hai site này).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Cách dùng &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;rblsmtpd&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; trong script run của “qmail-smtpd” đơn giản như sau:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;exec /usr/local/bin/softlimit -m 6291456 \&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    /usr/local/bin/tcpserver -v -p -x /etc/tcp.smtp.cdb -c "$MAXSMTPD" \&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;        -u "$QMAILDUID" -g "$NOFILESGID" 0 smtp &lt;/span&gt;&lt;b style="font-family: courier new;"&gt;/usr/local/bin/rblsmtpd -r relays.ordb.org -r relays.osirusoft.com&lt;/b&gt;&lt;span style="font-family: courier new;"&gt; /var/qmail/bin/qmail-smtpd &amp;gt;&amp;gt; /var/log/qmail/rblsmtpd.log 2&amp;gt;&amp;1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Chương trình &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;rblsmtpd&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; ở trên dùng hai tham số “relays.ordb.org” và “relays.osirusoft.com” chính là hai RBL database mà qmail phải đối chiếu mỗi khi nhận mail vào. Nếu Qmail nhận được dữ kiện từ một trong hai RBL database trên cho biết mail nào đó thuộc dạng “SPAM”, nó sẽ không tiếp nhận. Bạn có thể thêm các tham số cho &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;rblsmtpd&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; tùy thích.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Có lẽ bạn sẽ tự hỏi: vậy cứ mỗi lần mail đi vào đều phải được kiểm tra từ RBL thì chắc phải chậm lắm? Ðây là câu hỏi đã được đặt ra nhiều lần. Cá nhân tôi không thấy mức độ hoạt động của Qmail giảm sút khi đi qua giai đoạn kiểm tra này vì thật sự đây chỉ là một quy trình đối chiếu đơn giản. Nói cho cùng, dẫu có chậm hơn một tí vẫn còn nhanh hơn thời gian bạn phải ngồi xoá những bom thư bằng tay.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Một điểm cần lưu ý khi dùng các RBL database là nên theo dõi sự hiện diện của các RBL này. Lý do, các RBL này thường hoạt động theo tính thiện nguyện trên căn bản không lợi nhuận hoặc rất ít lợi nhuận nên tính trường tồn của chúng có phần bấp bênh. Nếu một trong những RBL bạn đang dùng không còn tồn tại thì nên cập nhật run script của “qmai-smtpd” nếu muốn duy trì nhiệm vụ kiểm tra SPAM của &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;rblsmtpd&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Tất nhiên bạn cũng có thể dùng RBL thương mại (phải trả tiền để dùng RBL database). Ðể cho tiện theo dõi, đây là danh sách cách RBL dabase cho chính Dan Bernstein, người viết Qmail và các phần mềm ứng dụng cho Qmail: &lt;/span&gt;&lt;a style="font-family: verdana;" target="_BLANK" href="http://cr.yp.to/ucspi-tcp/rblsmtpd.html"&gt;http://cr.yp.to/ucspi-tcp/rblsmtpd.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Hy vọng bạn sẽ hình thành một mail relay server bằng Qmail một cách hữu hiệu và tiện ích.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;(hnd - 13/1/2003)&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37459183-8032581914263665694?l=conmale.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://conmale.blogspot.com/feeds/8032581914263665694/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37459183&amp;postID=8032581914263665694' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/8032581914263665694'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/8032581914263665694'/><link rel='alternate' type='text/html' href='http://conmale.blogspot.com/2007/07/qmail-as-mail-gateway-phn-cui.html' title='Qmail as a Mail Gateway - Phần cuối'/><author><name>conmale</name><uri>http://www.blogger.com/profile/16598933828282382048</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/-2pIWb2iUysc/TzSYz5aVJYI/AAAAAAAAAAQ/BCWx8yVHmbU/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37459183.post-1439123797215032196</id><published>2007-07-09T10:33:00.000+10:00</published><updated>2007-07-09T10:35:41.286+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Qmail as a Mail Gateway - Phần 4</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;4. Hồ sơ điều chỉnh của Qmail trong “qmail-control”&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Có 28 hồ sơ thuộc thư mục “qmail-control”để đối ứng với tất cả mọi hoạt động của Qmail (và các phân bộ của Qmail). Ðối với trường hợp ứng dụng Qmail như một mail relay server, bạn không cần dùng trọn bộ 28 hồ sơ này. Ở đây, tôi sẽ dẫn ra trọn bộ 28 hồ sơ và phân nhóm chúng để dễ hiểu hơn.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;4.1 Danh mục các hồ sơ trong “qmail-control”&lt;br /&gt;&lt;br /&gt;Hồ sơ control        Thuộc vào chương trình&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;i style="font-family: verdana;"&gt;badmailfrom&lt;/i&gt;&lt;span style="font-family: verdana;"&gt;        &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;qmail-smtpd&lt;/b&gt;&lt;br /&gt;&lt;i style="font-family: verdana;"&gt;databytes&lt;br /&gt;localiphosts&lt;br /&gt;morercphosts&lt;br /&gt;rcpthosts&lt;br /&gt;smtpgreeting&lt;br /&gt;timeoutsmtpd&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;i style="font-family: verdana;"&gt;defaultdomain&lt;/i&gt;&lt;span style="font-family: verdana;"&gt;        &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;qmail-inject&lt;/b&gt;&lt;br /&gt;&lt;i style="font-family: verdana;"&gt;defaultroot&lt;br /&gt;idhost&lt;br /&gt;plusdomain&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;i style="font-family: verdana;"&gt;bouncefrom&lt;/i&gt;&lt;span style="font-family: verdana;"&gt;        &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;qmail-send&lt;/b&gt;&lt;br /&gt;&lt;i style="font-family: verdana;"&gt;bouncehost      &lt;br /&gt;concurrencylocal (concurincoming)&lt;br /&gt;concurrencyremote&lt;br /&gt;doublebouncehost&lt;br /&gt;doublebounceto&lt;br /&gt;envnoathost&lt;br /&gt;locals&lt;br /&gt;me&lt;br /&gt;percenthack&lt;br /&gt;queuelifetime&lt;br /&gt;virtualdomains&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;i style="font-family: verdana;"&gt;qmqpservers&lt;/i&gt;&lt;span style="font-family: verdana;"&gt;        &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;qmail-qmqpc&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;i style="font-family: verdana;"&gt;helohost&lt;/i&gt;&lt;span style="font-family: verdana;"&gt;            &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;qmail-remote&lt;/b&gt;&lt;br /&gt;&lt;i style="font-family: verdana;"&gt;smtproutes&lt;br /&gt;timeoutconnect&lt;br /&gt;timeoutremote&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;4.2 Danh mục các hồ sơ trong “qmail-control” cần thiết cho Qmail relay server:&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ngoại trừ bạn dùng Qmail để thiết lập một mail server hạng nặng và muốn xử dụng tối đa chức năng của mỗi chương trình trong Qmail suite, bạn sẽ hiếm khi phải xử dụng tới trọn bộ 28 hồ sơ ở trên. Với trường hợp Qmail là một relay server, bạn không cần quá một chục hồ sơ trong nhóm các hồ sơ thuộc &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;“qmail-control”&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Sau đây là danh sách các hồ sơ tôi dùng cho &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;“qmail-control”&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và nội dụng của từng hồ sơ để giúp bạn hình dung dễ dàng hơn chức năng của từng hồ sơ:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;4.2.1 Hồ sơ “me” thuộc qmail-send:&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Hồ sơ &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;“me”&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; là khởi điểm cho mọi hoạt động của Qmail, thiếu nó Qmail sẽ không chạy. Hồ sơ này được tạo ra từ bước &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;2.4.4&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; khi bạn chạy lệnh ./config để thiết lập hostname cho mail server của bạn. Hồ sơ này chỉ có một dòng chỉ định cho domain entry của mail relay server.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Nội dung của hồ sơ này có dạng: mail.mydomain.com, trong đó: mail là hostname của mail relay server, mydomain.com là fully qualified domain name bạn có.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;4.2.2 Hồ sơ “locals” thuộc qmail-send:&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Hồ sơ này dùng để chỉ định các địa chỉ e-mail được xem là “local” đối với mail relay server. Nếu không có entry nào trong &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;“locals”&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; thì qmail-send cho rằng chỉ có mỗi host trong &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;“me”&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; thuộc local. Trường hợp dùng Qmail như một mail relay server không cần &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;“locals”&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; nữa, nếu có, hồ sơ &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;“locals”&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; này có một dòng chỉ định y hệt như &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;“me”&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; vậy thôi.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;4.2.3 Hồ sơ “concurincoming”(hay còn gọi là concurrencylocal) thuộc qmail-send:&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Hồ sơ này ấn định số lượng mail được chuyển giao cùng một lúc. Default có giá trị là 10, với giá trị này, Qmail đủ sức chuyển giao mail cho một server cỡ nhỏ đến cỡ trung. Nên tránh dùng giá trị quá nhỏ để đề phòng trường hợp bị “denial attack”. Tôi dùng giá trị là 20 cho một văn phòng cỡ 100 nhân viên (khoảng 140 e-mails tổng cộng, bao gồm các e-mail chung cho từng nhóm nhân viên).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;4.2.4 Hồ sơ “defaultdomain” thuộc qmail-inject:&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Hồ sơ này dùng như một dạng bản mẫu, nếu vì một lý do gì đó mail client không dùng trọn bộ tên người dùng + tên domain như một e-mail thông thường ví dụ: &lt;/span&gt;&lt;a style="font-family: verdana;" href="mailto:me@mycom.com"&gt;me@mycom.com&lt;/a&gt;&lt;span style="font-family: verdana;"&gt; mà chỉ có tên người dùng là &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;me&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; thì “defaultdomain” được qmail dùng để “gắn” thêm cái đuôi tên domain trước khi nó gởi mail ra ngoài. Nếu qmail không tìm thấy “defaultdomain” nó sẽ tự động dùng entry trong hồ sơ “me” ở trên. Hồ sơ này không quá cần thiết, sự hiện diện của nó thường để loại trừ trường hợp mail client không gởi “sender” đúng và dùng để giao chuyển giữa các mail account trong cùng mail relay server.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Hồ sơ này chỉ đơn giản có 1 entry là domain name của bạn, ví dụ: &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;mycompany.com&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;4.2.5 Hồ sơ “queuelifetime” thuộc hồ sơ qmail-send:&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Hồ sơ này dùng để chỉ định thời gian (tính theo đơn vị giây) mail được giữ trong mail queue (vì lý do gì đó không chuyển gởi được) trước khi bị xoá. Khi mail đợi trong queue đến hạn cuối của “queuelifetime”, qmail sẽ chuyển gởi mail đó lần cuối trước khi thực sự xoá nó khỏi mail queue (nếu mail này vẫn không thể chuyển giao được).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Giá trị default của hồ sơ &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;“queuelifetime”&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; là 604800 giây (tương đương với 1 tuần lễ). Giá trị này tùy thuộc vào môi trường của bạn mà thiết lập cho thích hợp. Ví dụ, mail relay server của bạn chỉ phục vụ cho một số ít người và thuộc mạng “chậm” thì nên thiết kết giá trị của “queuelifetime” cao hơn một tí để mail có cơ hội được chuyển giao trong trường hợp mạng bi nghẽn (thật ra queuelifetime cho 1 tuần là rất lâu). Tôi chọn giá trị 172800 (khoảng 48 giờ) vì mail relay server trong trường hợp tôi thiết kế phục vụ cho khá nhiều người và đường dẫn khá tốt.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;4.2.6 Hồ sơ “badmailfrom” thuộc qmail-smtpd:&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Hồ sơ này là một trong những hồ sơ tiện dụng của qmail, nó dùng để chứa các e-mail bạn không cho phép qmail server nhận vào (nó thuộc qmail-smtpd nên thuộc phần “nhận”). Dù phương pháp chống “bom thư” hay spam này không được linh động cho lắm nhưng nó là một trong những chức năng chứng tỏ sự quan tâm của ông Bernstein khi viết Qmail trong vấn đề chống spam.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Hồ sơ này chứa các e-mail hoặc trọn bộ domain bạn không muốn nhận bất cứ tin tức gì, mỗi e-mail phải nằm trên một dòng. Ví dụ:&lt;/span&gt;&lt;br /&gt;&lt;a style="font-family: verdana;" href="mailto:spamboy@spamhouse.com"&gt;spamboy@spamhouse.com&lt;/a&gt;&lt;span style="font-family: verdana;"&gt; (không nhận mail từ 1 địa chỉ này)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;@spamhouse.com (không nhận mail từ trọn bộ domain này).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Các phương pháp phòng chống “bom thư” linh động hơn sẽ được đi sâu hơn trong những phần tới.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;4.2.7 Hồ sơ “rpcthosts” thuộc qmail-smtpd:&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Hồ sơ rcpthosts là một hồ sơ hết sức quan trọng đối với qmail-smtpd, nhất là cho một mail relay server. Hồ sơ này cung cấp dữ kiện cho &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;qmail-smtpd&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;, daemon này thay mặt các hosts và domains nào muốn nhận chuyển mail. Ví dụ bạn có 2 mail server trong LAN nội bộ có tên là domain1.com và domain2.com, hồ sơ &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;rcpthosts&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; phải có dữ kiện của 2 mail server này, nếu không, mail từ bên ngoài vào 2 server này sẽ bị &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;qmail-smtpd&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; từ chối chuyển nhận vào bên trong. Nên nhớ phải có &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;ít nhất là một dữ kiện cho chính mail relay server&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; không thì sẽ không có mail nào được vào (ngay cả cho chính mail relay server).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Hồ sơ rcpthosts chứa các dữ kiện theo mặc định &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;mỗi dòng một host/domain&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Hồ sơ này có cấu trúc tương tự như sau:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;mail.mydomain.com (mail là hostname của mail relay server và domain.com là fully qualified domain name. Ðây chính là dữ kiện thiết yếu và đầu tiên cho mail relay server).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;exchange1.mydomain.com (exchange1 là hostname của MS exchange thuộc LAN nội bộ. Tất nhiên DNS của bạn (hoặc của ISP cung cấp cho bạn) phải có entry cho host exchange1 này và mail relay server phải biết được địa chỉ (bên trong) của host exchange1).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;exchange2.mydomain.com (tương tự như exchange1 và nhiều mail server bên trong theo cấu trúc này nếu cần).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;mydomain.net (giả sử bạn có thêm một domain name khác với đuôi .net và một trong những mail server thuộc LAN nội bộ đã thiết lập để nhận mail cho domain.net này, entry domain.net trong rcpthosts cần thiết để mail relay server biết domain.net &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;được phép nhận&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; mail từ bên ngoài thông qua mail relay server).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;mail.myfriend.com (giả sử một người bạn có domain name là &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;myfriend.com&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và anh ta bị trục trặc với mail server. Bạn có thể “tạm thời” giúp anh ta bằng cách cho phép mail relay server của bạn nhận các mail thuộc &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;myfriend.com&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; vào host &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;mail&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; để anh ta có thể dial in host mail này mà lấy mail (chẳng hạn). Kỹ thuật này còn có cái tên là “chuyển nhận có lựa chọn” (selective relay policy).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Sự hiện diện của hồ sơ rpcthosts là một trong những đặc thù của qmail trong vấn đề phòng chống open-relay. Chỉ có những host/domain hiện diện trong rpcthosts được phép nhận mail từ mai relay server của bạn. Ðiều này có nghĩa, một người ở hostA (mang IP address xx.xx.xx.xx) có ý định dùng mail relay server của bạn để chuyển tới một mail server nào đó (có IP address zz.zz.zz.zz) ngoài giới hạn quy định của rpcthosts &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;tuyệt đối không thể được&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Phần &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;“Thử nghiệm sau khi cài đặt”&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; trong phần 6 sẽ đi xuyên qua một số bước kiểm tra cụ thể.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;4.2.8 Hồ sơ “smtpgreeting” thuộc qmail-smtpd:&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Hồ sơ này trên mặt chức năng gần như không cần thiết nhưng trên mặt tâm lý nó mang ít nhiều tính chuyên nghiệp (professionalism) sự sắp xếp và hiện diện của một mail relay server trên Internet. Hồ sơ smtpgreeting không chứa gì ngoài một giòng thông điệp “chào mừng” những ai đến mail relay server này (bao gồm sự trao đổi giữa các mail relay servers và ngay cả các tay chuyên dùng telnet hoặc các loại dụng cụ thăm dò mail server lỗ hổng open-relay).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Hồ sơ này tùy thuộc vào tinh thần của bạn mà hình thành một lời “chào mừng” đúng mức. Tôi đã từng thấy một số mail relay server có lời “chào mừng” khá thách thức chẳng hạn như: “Kiddies, this server is not your playground. Stay away or stick around for a challenge” (Tạm dịch: &lt;/span&gt;&lt;i style="font-family: verdana;"&gt;Mấy ông nhóc con, server này không phải là chỗ chơi của các ông. Tránh xa hay nhào vô mà thử thách&lt;/i&gt;&lt;span style="font-family: verdana;"&gt;). Dù cơ chế làm việc của qmail mang nặng tính bảo mật không có nghĩa là nó hoàn hảo và không cách gì phá được. Một thông điệp mang tính hoà nhã và nghiêm túc thường có tác dụng tốt đẹp hơn nhiều (bạn sẽ phải hối hận nếu lỡ buông lời thách thức trong thế giới bảo mật).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Tôi giả định nên dùng một thông điệp ngắn gọn và rõ ràng như sau: “Welcome to company ABC mail server and have a nice time”. Xét cho cùng, bạn không muốn tạo nên phiền toái mà làm gì. Nếu một tay chuyên tìm open-relay thất vọng khi “đụng” phải mail server của bạn đã là một thành tựu; một thông điệp nhẹ nhàng sẽ giúp cho anh ta quyết định “để yên server” của bạn. Nên nhớ rằng, dù mail relay server của bạn không open-relay,  những kẻ muốn phá vẫn có thể “flood” server của bạn được, tổn thất ở chỗ người dùng trong nội mạng không có cơ hội gởi và nhận mail trong khi mail relay server bị “flood”.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;4.2.9 Hồ sơ “smtproutes” thuộc qmail-remote:&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Ðối với một mail server bình thường (qmail được thiết kế để trực tiếp nhận / gởi e-mail từ clients bên trong nội mạng và các mail server ngoại mạng), hồ sơ &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;smtproutes&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; không cần thiết. Tuy nhiên, để một qmail relay server làm việc, hồ sơ này không thể thiếu được. Hồ sơ này tương tự hồ sơ rcpthosts ở trên chỉ có thêm giá trị địa chỉ IP đi sau mỗi host (mail server trong nội mạng). Các IP của mail server trong nội mạng giúp mail relay server xác định được mail sẽ được chuyển về đâu và mỗi mail server nội mạng chịu trách nhiệm phân phát cho các clients theo đúng quy định. Ðây chính là cốt yếu khác biệt giữa một mail server bình thường và một mail relay server.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Hồ sơ smtproutes có cấu trúc như sau: hostname.domain.com:[IP_ADDRESS]. Giả sử hai exchange mail servers trong nội mạng có tên là exchange1 (IP: 192.168.1.100) và exchange2 (IP: 192.168.1.200), dữ kiện được quy định trong smtproutes sẽ như sau:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;exchange1.mydomain.com:[192.168.1.100]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;exchange2.mydomain.com:[192.168.1.200]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;mail.myfriend.com:[192.168.1.100] (dùng exchange1 để “nhận dùm” mail cho người bạn, tất nhiên exchange1 đã được thiết kế để tiếp nhận mail cho domain myfriend.com).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;4.3 Mail server trong nội mạng (MS Exchange)&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Tôi chọn MS Exchange như một mail server nội mạng không phải vì khả năng chuyên biệt của MS Exchange mà vì tính phổ biến của nó trong môi trường văn phòng thường xử dụng MS Back Office. Cách điều chỉnh cho các loại mail server khác có những điểm tương tự như MS Exchange về phương diện mail đi ra / vào (thay vì đi vào trực tiếp từ mail server của ISP bạn dùng, MS Exchange hoặc mail server nào đó có thể đi vào từ Qmail mail relay server).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Trong phần điều chỉnh Connections của MS Exchange, bạn chọn “Internetmail Service Properties”. Trong phần điều chỉnh này có một “tab” gọi là “Connection”, trong đó bạn có thể điều chỉnh hai dữ kiện để MS Exchange biết phải chuyển nhận mail từ Qmail mail relay server ở đâu:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Transfer mode&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; chọn: “Inbound and Outbound”&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Message delivery&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; chọn: “Forward all messages to host” và IP của host chính là IP của mail relay server.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Nếu Exchange server của bạn chịu trách nhiệm quản lý mail cho nhiều domain, bạn phải điều chỉnh “Reroute incoming SMTP mail” cho thích ứng trong “tab” Routing của “Internet Mai Properties. Những thiết lập này mang tính cụ thể cho từng loại mail server. Bạn nên tham khảo thêm tài liệu của mỗi loại mail server để đi sâu vào các chi tiết.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Nguyên tắc làm việc trước và sau khi có mail relay server là:&lt;/span&gt;&lt;br /&gt;&lt;i style="font-family: verdana;"&gt;* Các mail server thuộc nội mạng (hoặc DMZ) không còn truy cập trực tiếp đến mail server của ISP mà truy cập vào Qmail relay server.&lt;br /&gt;* Cơ chế mail relay hoàn toàn do qmail server nắm giữ.&lt;br /&gt;* Qmail relay server có thể được nằm trong DMZ hoặc nội mạng hoặc đằng sau một router miễn sao router + firewall có thể “foward” các thông tin từ bên ngoài vào mail relay server. Quyết định đặt để qmail relay server tùy thuộc vào cấu trúc của từng network.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;(còn tiếp)&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37459183-1439123797215032196?l=conmale.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://conmale.blogspot.com/feeds/1439123797215032196/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37459183&amp;postID=1439123797215032196' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/1439123797215032196'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/1439123797215032196'/><link rel='alternate' type='text/html' href='http://conmale.blogspot.com/2007/07/qmail-as-mail-gateway-phn-4.html' title='Qmail as a Mail Gateway - Phần 4'/><author><name>conmale</name><uri>http://www.blogger.com/profile/16598933828282382048</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/-2pIWb2iUysc/TzSYz5aVJYI/AAAAAAAAAAQ/BCWx8yVHmbU/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37459183.post-3334242666166454226</id><published>2007-06-28T11:20:00.000+10:00</published><updated>2007-07-09T10:35:49.318+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Qmail as a Mail Gateway - Phần 3</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;3.4.2 Thư mục “qmail-smtpd” trong supervise&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Tương tự như trên, bạn tạo ra hồ sơ có tên là run trong thư mục &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;/var/qmail/supervise/qmail-smtpd&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Hồ sơ run này có trách nhiệm gọi một số phân bộ quan trọng của qmail để thi hành các chức năng trực thuộc smtp. Hồ sơ “run” này có chi tiết như sau:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;&lt;span style="font-family: courier new;"&gt;#!/bin/sh&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;# concurincoming is not standard qmail control file&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;# it is created manually to specify the allowed concurrent incoming messages&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;#&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;QMAILDUID=`id -u qmaild`&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;NOFILESGID=`id -g qmaild`&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;MAXSMTPD=`cat /var/qmail/control/concurincoming`&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;if [ -z "$QMAILDUID" -o -z "$NOFILESGID" -o -z "$MAXSMTPD" ]; then&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;        echo QMAILDUID, NOFILESGID, or MAXSMTPD is not set in&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;        echo /var/qmail/supervise/qmail-smtpd/run&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    echo “Have you set qmaild UID &amp; qmaild GID yet?”&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;        exit 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;     fi&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;exec /usr/local/bin/softlimit -m 6291456 \&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;    /usr/local/bin/tcpserver -v -p -x /etc/tcp.smtp.cdb -c "$MAXSMTPD" \&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;        -u "$QMAILDUID" -g "$NOFILESGID" 0 smtp /var/qmail/bin/qmail-smtpd 2&amp;gt;&amp;1&lt;/span&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Hồ sơ này sẽ có thêm một vài thông số quan trọng cho vấn đề chống “SPAM” sẽ được đi sâu hơn trong phần 5.4 sau này. Ở đây, bạn chỉ cần nắm bắt một vài chi tiết quan trọng đó là: &lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;- softlimit -m $MEMSIZE&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; trong đó, &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;$MEMSIZE&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; là số lượng memory thích hợp cho các phân bộ của qmail để xử lý khối lượng mail cao nhất trong khoảng thời gian bận rộn nhất.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;- tcpserver&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và các thông số &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;-p -x&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; trong đó, &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;-p&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; chỉ định cho tình trạng “hoảng” (paranoid) dùng để kiểm tra IP của host gởi mail đến xem domain, MX record và IP của nó có giá trị hay không (tránh tình trạng SPAM theo phương thức đơn giản). &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;-x&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; chỉ định cho tcpserver dùng database (trong phần 3.4 sau đây) để kiểm tra chế độ nhận hoặc từ chối mail từ người gởi dựa trên database này.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;- concurincoming&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; variable trong hồ sơ “run” dùng để chỉ định số lượng mail được “đi vào” mail gateway mỗi lần. Bạn có thể cho nó một con số thích đáng tùy theo nhu cầu. Tuy nhiên, không nên cho concurincoming có giá trị quá cao để phòng ngừa khả năng bị DOS. Tôi chọn giá trị là 20 cho concurincoming, giá trị này đủ sức xử lý vài trăm đến vài ngàn mail mỗi giờ (tùy theo dung tích của mail đi xuyên qua mail gateway).&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# echo 20 &amp;gt; /var/qmail/control/concurincoming&lt;br /&gt;# chmod 644 /var/qmail/control/concurincoming&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Ðừng quên đổi hồ sơ “run” này thành “executable”:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# chmod 755 /var/qmail/supervise/qmail-smtpd/run&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Bước kế tiếp là tạo ra hồ sơ “run” trong thư mục /var/qmail/supervise/qmail-smtpd/log. Hồ sơ này gọi &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;multilog&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; thi hành nhiệm vụ logging cho các lưu thông thuộc phần hành smtp, &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;multilog&lt;/b&gt; chuyển các log thuộc smtp vào thư mục /var/log/qmail/smtpd; nó có chi tiết như sau:&lt;br /&gt;&lt;b style="font-family: courier new;"&gt;#!/bin/sh&lt;br /&gt;# set user id and group id for qmail smtp daemon&lt;br /&gt;exec /usr/local/bin/setuidgid qmaill /usr/local/bin/multilog t s5000000000 /var/log/qmail/smtpd&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Ðừng quên đổi hồ sơ “run” này thành “executable”:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# chmod 755 /var/qmail/supervise/qmail-smtpd/log/run&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Cuối cùng là tạo thư mục log cho qmail-smtpd:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# mkdir -p /var/log/qmail/smtpd&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Và đổi chủ quyền của thư mục này cho qmaill (bạn còn nhớ phần tạo tài khoản nhân dụng và nhóm nhân dụng ở phần 2.4.3?):&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# chown qmaill /var/log/qmail /var/log/qmail/smtpd&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;3.5 Bộ quản trị “SMTP Access Control”&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Trong qmailctl có một function chuyên chịu trách nhiệm cho phần SMTP access control. Bạn xem lại &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;qmailctl&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; sẽ thấy có dòng như sau thuộc function &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;cdb&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;cat /etc/smtprules/qmail-rules.txt | tcprules /etc/tcp.smtp.cdb&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Lệnh trên có hai phần: copy qmail-rules.txt và pipe nó sang tcprules để biến nó thành hash database. Database này chứa các thông tin để kiểm tra chế độ nhận hoặc từ chối mail từ người gởi như đã đề cập trong phần 3.4.2 ở trên.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Bạn có thể tạo một hồ sơ có tên là qmail-rules.txt trong thư mục /etc/smtprules và có chi tiết như sau:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Tạo thư mục /etc/smtprules trước:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# mkdir – p /etc/smtprules&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Ðưa chi tiết vào hồ sơ qmail-rules.txt:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# echo '127.:allow,RELAYCLIENT=””' &amp;gt;&amp;gt; /etc/smtprules/qmail-rules.txt&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Lệnh trên đưa vào policy cho phép các host thuộc loopback được phép relay, nếu không Qmail không làm việc được.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# echo '192.168.1.:allow,RELAYCLIENT=””' &amp;gt;&amp;gt; /etc/smtprules/qmail-rules.txt&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Lệnh trên đưa vào policy cho phép trọn bộ các client thuộc subnet 192.168.1.0/24 được quyền gởi mail đến Qmail gateway&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# echo '10.10.10.50:allow,RELAYCLIENT=””' &amp;gt;&amp;gt; /etc/smtprules/qmail-rules.txt&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Lệnh trên đưa vào policy cho phép một IP address (có thể là MS Exchange Server bên trong một subnet của LAN) được quyền relay.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# echo '&lt;a href="mailto:spamboy@spamhouse.com"&gt;spamboy@spamhouse.com&lt;/a&gt;:deny' &amp;gt;&amp;gt; /etc/smtprules/qmail-rules.txt&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Lệnh trên đưa vào policy từ chối mail từ người gởi có tên spamboy từ domain spamhouse.com. Cách này là cách đơn giản đề phóng chống bomb mail. Trên thực tế ứng dụng có nhiều phương pháp hữu hiệu hơn (sẽ bàn sâu hơn trong phần 5.4 sau này).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# echo 'badhost.net:deny' &amp;gt;&amp;gt; /etc/smtprules/qmail-rules.txt&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Lệnh trên đưa vào policy từ chối mail của trọn bộ domain badhost.com. Bạn có thể dùng phương cách :allow hoặc :deny một cách linh động cho thích hợp với nhu cầu riêng. Và cuối cùng của hồ sơ qmail-rules.txt này, bạn luôn luôn cần một dòng như sau:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;.:deny (&lt;/span&gt;&lt;b style="font-family: verdana;"&gt;# echo '.:deny' &amp;gt;&amp;gt; /etc/smtprules/qmail-rules.txt&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;) với tác dụng từ chối tất cả các trường hợp còn lại.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Hồ sơ qmail-rules.txt đến đây tương tự như sau:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;127.:allow,RELAYCLIENT=””&lt;br /&gt;192.168.1.:allow,RELAYCLIENT=””&lt;br /&gt;10.10.10.50:allow,RELAYCLIENT=””&lt;br /&gt;&lt;a href="mailto:spamboy@spamhouse.com"&gt;spamboy@spamhouse.com&lt;/a&gt;:deny&lt;br /&gt;badhost.net:deny&lt;br /&gt;.:deny&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Sau khi đã hoàn tất hồ sơ qmail-rules.txt như ý (đúng syntax như trên cho :allow, :deny) bạn có thể dùng function cdb của qmailctl:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# qmailctl cdb&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Hoặc kiểu “dài dòng”:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# cat /etc/smtprules/qmail-rules.txt | tcprules /etc/tcp.smtp.cdb&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Cũng nên đi vào chi tiết của &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;tcprules&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; syntax để giúp bạn tạo thêm các rules theo ý muốn và tránh những sai sót có thể xảy ra. Syntax của tcprules rất đơn giản như sau:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;address:action,variable&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Trong đó,&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;address&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; có thể là một &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;internet address&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; (192.168.1.1), một chuỗi &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;subnet&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; (192.168.1.), một &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;e-mail address&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; (&lt;/span&gt;&lt;a style="font-family: verdana;" href="mailto:spamboy@spamhouse.com"&gt;spamboy@spamhouse.com&lt;/a&gt;&lt;span style="font-family: verdana;"&gt;), một &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;domain host&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; (badhost.net) hoặc nếu không chỉ định một address nào thì bất cứ address cũng ứng dụng. Các variables của &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;address&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; có thể tóm gọn như sau:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;$TCPREMOTEINFO@$TCPREMOTEIP (&lt;/span&gt;&lt;a style="font-family: verdana;" href="mailto:spamboy@192.168.1.1"&gt;spamboy@192.168.1.1&lt;/a&gt;&lt;span style="font-family: verdana;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;$TCPREMOTEINFO@$TCPREMOTEHOST (&lt;/span&gt;&lt;a style="font-family: verdana;" href="mailto:spamboy@spamhouse.com"&gt;spamboy@spamhouse.com&lt;/a&gt;&lt;span style="font-family: verdana;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;$TCPREMOTEIP (192.168.1.1)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;$TCPREMOTEHOST (box.spamhouse.com)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Một phần của $TCPREMOTEIP (192.168.1)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Một phần của $TCPREMOTEHOST (spamhouse.com)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Không để address (bất cứ address nào cũng ứng dụng)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;action&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; là một trong hai trường hợp &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;allow&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; dành để &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;cho phép&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; address đã định hoặc &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;deny&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; dành để &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;từ chối&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; address đã định.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;variable&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; đi sau &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;action&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; được tách ra bởi dấu phẩy (,) (comma separated) thông thường là variable RELAYCLIENT với giá trị là một empty string (RELAYCLIENT=””)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;3.6 Tạo ảo dụng “alias” cho Qmail&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;“alias” đóng vai trò quan trọng trong vấn đề quản lý mail server, điều này có nghĩa mỗi “alias” là một “ảo nhân” chịu trách nhiệm cho một số trường hợp điển hình của các hoạt động trên một mail server. Sau đây là 3 “alias” cần thiết nhất :&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;- postmaster&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; (theo đúng RFC 2821) chỉ cho Administrator của mail server&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;- mailer-daemon&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; một loại người dùng bán tiêu chuẩn để nhận các mail bị dội (bounce)&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;- root&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; dùng để chuyển các loại mail mang tính chủ quyền đến system administrator&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Giả sử bạn muốn mailbox của chính mình lo luôn cả 3 alias ở trên, bạn cần ra các lệnh sau:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# echo myname &amp;gt; /var/qmail/alias/.qmail-root&lt;br /&gt;# echo myname &amp;gt; /var/qmail/alias/.qmai-postmaster&lt;br /&gt;# ln -s /var/qmail/alias/.postmaster /var/qmail/alias/.qmail-mailer-daemon&lt;br /&gt;# chmod 644 /var/qmail/alias/.qmail-root /var/qmail/alias/.qmail-postmaster&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Nên nhớ các alias trên đều là hồ sơ “dấu” (hidden files) nên chúng đều có dấu chấm (.) đằng trước tên của alias. Các alias này có thể dùng để chuyển mail đến các user trên Unix (hoặc Linux), tôi không đi sâu vào vấn đề này vì chủ đề của bài viết là dùng Qmail như một mail gateway để forward mail vào một MTA bên trong LAN (như MS Exchange chẳng hạn).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ðến đây Qmail có thể hoạt động được. Tuy nhiên, có một số vấn đề còn phải thử nghiệm và điều chỉnh để hoàn thiện các configuration của Qmail và daemontools. Ðây là các bước quan trọng và sẽ được đi sâu trong phần kế tiếp.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;(còn tiếp)&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37459183-3334242666166454226?l=conmale.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://conmale.blogspot.com/feeds/3334242666166454226/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37459183&amp;postID=3334242666166454226' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/3334242666166454226'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/3334242666166454226'/><link rel='alternate' type='text/html' href='http://conmale.blogspot.com/2007/06/qmail-as-mail-gateway-phn-3.html' title='Qmail as a Mail Gateway - Phần 3'/><author><name>conmale</name><uri>http://www.blogger.com/profile/16598933828282382048</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/-2pIWb2iUysc/TzSYz5aVJYI/AAAAAAAAAAQ/BCWx8yVHmbU/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37459183.post-3299642518141965385</id><published>2007-06-26T08:10:00.000+10:00</published><updated>2007-06-26T08:28:04.629+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Qmail as a Mail Gateway - Phần 2</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;3. Thiết lập ứng dụng Qmail&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;3.1 Hồ sơ rc và “defaultdelivery”&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Hồ sơ “rc” là boot script của qmail ấn định phương thức chuyển giao mail tùy theo cách sắp xếp và chọn lựa của từng hệ thống. Trong thư mục /var/qmail/boot có sẵn một số script cho từng trường hợp.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Nếu bạn không dùng &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;daemontools&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; mà dùng &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;splogger&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; của qmail để gởi log xuyên qua syslog (tiêu chuẩn Unix) và binmail để chuyển giao thông điệp theo phương thức /var/spool/mail/$USER thì “rc” script tương tự như sau:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Ví dụ thứ nhất:&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;#!/bin/sh&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;# Dùng splogger để chuyển log xuyên qua syslog&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;# Dùng binmail để chuyển giao thông điệp đến /var/spool/mail/$USER theo default&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;# Dùng V7 binmail interface: /bin/mail -f&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;exec env – PATH=”/var/qmail/bin:$PATH” \&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;qmail-start  \&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;`|preline -f /bin/mail -f "${SENDER:-MAILER-DAEMON}" -d "$USER"` \&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;splogger mail &lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Trong đó,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Phương thức chuyển giao mail đến /var/spool/mail/$USER chính là phương thức chuyển giao mail theo truyền thống Unix.Nếu bạn muốn hiểu rõ hơn, nên tham khảo thêm phương thức chuyển giao mail của Unix.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Các dấu back-slash (\) chỉ cho sự nối tiếp trong câu lệnh (\ là return character)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Phần lệnh h &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;preline -f /bin/mail -f&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; của người gởi là &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;MAILER-DAEMON&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; đến &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;$USER&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; nằm trong dấu backquote (`) chớ không phải là singlequote ('). Nên phân biệt rõ các dấu quote này khi đánh lệnh trên trong script “rc” (backquote dùng để ứng thế một cụm lệnh, singlequote chỉ là một singlequote). Nếu bạn muốn hiểu rõ hơn về khả năng “command subtitution” trên Unix, nên đọc thêm phần này.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Dĩ nhiên bạn có thể tạo nên một “rc” như trên và dùng splogger. Tuy nhiên, nếu đã install daemontools, tại sao không tận dụng chức năng của nó? Hồ sơ “rc” của tôi như sau:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Ví dụ thứ nhì:&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;#!/bin/sh&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;# Dùng multilog của daemontools để gởi log đến /var/log/qmail&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;# Dùng /var/qmail/control/defaultdelivery làm hồ sơ configuration&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;# Dùng ./Mailbox làm phương thức chuyển giao thông điệp&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;exec env – PATH=”/var/qmail/bin:$PATH” \&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;qmail-start “`cat /var/qmail/control/defaultdelivery`”&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- So với hồ sơ “rc” ở trên dùng splogger và hồ sơ “rc” dùng daemontools này thì hồ sơ “rc” này giản tiện hơn nhiều.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Lệnh &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;exec env&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; xác định môi trường qmail và &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;qmail-start&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; chỉ đơn giản khởi động theo thông số  đã định sẵn trong defaultdelivery.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- defaultdelivery không phải là một hồ sơ tiêu chuẩn của qmail. Nó đơn giản chỉ là một phương tiện gởi thông số cho qmail-start.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Sau khi đã tạo ra hồ sơ “rc” trong thư mục /var/qmail, có hai việc cần làm là:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Thay “mod” của hồ sơ này thành “executable: &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;# chmod 755 /var/qmail/rc&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; để script rc này có thể “khởi động” được khi cần.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Tạo ra thư mục /var/log/qmail để daemontools gởi log của qmail vào vị trí này: &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;# mkdir /var/log/qmail&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; (nếu bạn không muốn dùng daemontools mà chỉ dùng rc như phần ví dụ thứ nhất thì không cần tạo ra thư mục này vì splogger sẽ dùng syslog).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ðến đây có lẽ bạn sẽ hỏi: defaultdelivery ở đâu ra và trong hồ sơ này chứa những gì? Như đã đề cập ở trên, defaultdelivery chỉ đơn giản là một phương tiện gởi thông số cho qmail-start; nó giúp qmail-start xác định phương thức chuyển gởi mail (nếu không muốn dùng .qmail). Có 3 phương thức chuyển gởi mail thông thường trên Unix như sau:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Format    Vị trí    defaultdelivery    Lợi điểm&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;maildir    $HOME    ./Maildir/        Ðáng tin cậy nhưng ít MUA hỗ trợ&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;mbox    $HOME    ./Mailbox        Phổ biến và được các MUA hỗ trợ&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;username    /var/spool/mail xem thêm INSTALL.vsm   Mail tiêu chuẩn Unix.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Dựa vào bảng phân tích trên, bạn có thể chọn phương thức thích hợp cho mình. Trong thư mục mã nguồn có kèm các hồ sơ INSTALL.mbox, INSTALL.maildir và INSTALL.vsm giải thích rất chi tiết các ưu khuyết điểm của từng phương thức nếu bạn muốn tìm hiểu sâu hơn. Cá nhân tôi chọn ./Mailbox vì muốn tạo tiện dụng cho các MUA (Mail User Agent).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Vậy, để tạo ra defaultdelivery, bạn chỉ cần chọn một phương thức và dùng lệnh echo để đính phương thức đã chọn, giả sử như:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# echo ./Mailbox &amp;gt; /var/qmail/control/defaultdelivery&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Trong đó,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- ./Mailbox là phương thức.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- hồ sơ defaultdelivery được nằm trong thư mục /var/qmail/control, nơi trọn bộ các configuration thuộc qmail được lưu trữ.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- lệnh echo đính dòng &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;./Mailbox&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; (&amp;gt;) vào hồ sơ defaultdelivery.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;3.2 Hồ sơ khởi động “qmailctl” của hệ điều hành&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ðến đây, bạn đã có thể khởi động qmail bằng cách chạy script “rc” đã tạo ở trên. Tuy nhiên, để qmail được ứng dụng như một mail gateway có khả năng tự khởi động và tự tắt theo đúng quy chế thì “rc” không có khả năng này. Hơn nữa, các chức năng tiện dụng của phần daemontools không được ứng dụng đầy đủ nếu chỉ dùng script “rc” ở trên. Hồ sơ “rc” sẽ được dùng như một phân bộ trong cơ chế chuyển gởi thông điệp (qua smtp), các phần kế tiếp sẽ đi sâu hơn.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Vì lý do trên, hồ sơ khởi động &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;qmailctl&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; được hình thành để quản lý các phân bộ của qmail và daemontools đúng hệ thống. Trước khi đi sâu vào nội dung của hồ sơ qmailctl, bạn cần biết qua một số binaries và các chức năng của chúng trong phần mềm hỗ trợ “daemontools” để dễ hình dung cơ chế làm việc của hồ sơ qmailctl.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Sau khi compile và build daemontools thành công, phần mềm này có 14 binaries được lưu trữ trong /usr/local/bin, bạn chỉ cần biết đến một số binaries và chức năng của chúng như sau:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Tên binary    Chức năng&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;supervise:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Dùng để khởi động và theo dõi một process. Có khả năng tái khởi động process đó nếu nó bị “chết”&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;svok:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Dùng để kiểm tra xem supervise đang thao tác hay không&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;svc:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Dùng để điều khiển một process được khởi động bởi supervise, binary này cho phép Admin ngưng và tái khởi động một process nào đó.&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;svstat:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Dùng để báo cáo tình hình của một process được khởi động bởi supervise&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;svscan:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Dùng để khởi động vào theo dõi một nhóm process được supervise tạo ra&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Theo đây là một bản mẫu của hồ sơ qmailctl, bạn có thể dùng nó cho hệ thống của mình nếu không muốn tự tạo một “qmailctl” riêng:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: courier new;"&gt;#!/bin/sh&lt;br /&gt;# Người dùng RedHat có thể giản tiện chu trình sắp xếp&lt;br /&gt;# “runlevel” với lệnh “chkconfig”&lt;br /&gt;# chkconfig: - 80 30&lt;br /&gt;# description: qmail as MTA&lt;br /&gt;&lt;br /&gt;# Phần kế tiếp dùng để chỉnh user environment&lt;br /&gt;PATH=/var/qmail/bin:/bin:/usr/bin:/usr/local/bin:/usr/local/sbin&lt;br /&gt;export PATH&lt;br /&gt;&lt;br /&gt;# Xác định variables cho qmail daemon ID và user group ID&lt;br /&gt;QMAILDUID=`id -u qmaild`&lt;br /&gt;NOFILESGID-`id -g qmaild`&lt;br /&gt;&lt;br /&gt;# Bắt đầu tạo ra các trường hợp hoạt dụng cho supervise&lt;br /&gt;case “$1” in&lt;br /&gt;start)&lt;br /&gt;echo -n “Starting qmail: svscan”&lt;br /&gt;cd /var/qmail/supervise&lt;br /&gt;env – PATH=”$PATH” svscan &amp;&lt;br /&gt;echo $! &amp;gt; /var/run/svscan.pid&lt;br /&gt;echo “.”&lt;br /&gt;;;&lt;br /&gt;stop)&lt;br /&gt;echo -n “Stopping qmail: svscan&lt;br /&gt;kill `cat /var/run/svscan.pid`&lt;br /&gt;echo -n “ qmail down”&lt;br /&gt;svc -dx /var/qmail/supervise/*&lt;br /&gt;echo -n “ logging down too”&lt;br /&gt;svc -dx /var/qmail/supervise/*/log&lt;br /&gt;echo “.”&lt;br /&gt;;;&lt;br /&gt;stat)&lt;br /&gt;cd /var/qmail/supervise&lt;br /&gt;svstat * */log&lt;br /&gt;;;&lt;br /&gt;doqueue)&lt;br /&gt;echo “Sending ALRM signal to qmail-send”&lt;br /&gt;svc -a /var/qmail/supervise/qmail-send&lt;br /&gt;;;&lt;br /&gt;queue)&lt;br /&gt;qmail-qstat&lt;br /&gt;qmail-qread&lt;br /&gt;reload)&lt;br /&gt;echo “Sending HUP signal to qmail-send”&lt;br /&gt;svc -h /var/qmail/supervise/qmail-send&lt;br /&gt;;;&lt;br /&gt;pause)&lt;br /&gt;echo “Pausing qmail-send”&lt;br /&gt;svc -p /var/qmail/supervise/qmail-send&lt;br /&gt;echo “Pausing qmail-smtpd”&lt;br /&gt;svc -p /var/qmail/supervise/qmail-smtpd&lt;br /&gt;;;&lt;br /&gt;cont)&lt;br /&gt;echo “Continuing qmail-send”&lt;br /&gt;svc -c /var/qmail/supervise/qmail-send&lt;br /&gt;echo “Continuing qmail-smtpd”&lt;br /&gt;svc -c /var/qmail/supervise/qmail-smtpd”&lt;br /&gt;;;&lt;br /&gt;restart)&lt;br /&gt;echo “Restarting qmail:”&lt;br /&gt;echo “* Stopping qmail-smtpd”&lt;br /&gt;svc -d /var/qmail/supervise/qmail-smtpd&lt;br /&gt;echo “* Sending qmail-send SIGTERM and restarting”&lt;br /&gt;svc -t /var/qmail/supervise/qmail-send&lt;br /&gt;echo “* Restarting qmail-smtpd”&lt;br /&gt;svc -u /var/qmail/supervise/qmail-smtpd&lt;br /&gt;;;&lt;br /&gt;cdb)&lt;br /&gt;echo “Do not forget to modify /etc/smtprules/qmail-rules.txt or it will use the old cdb”&lt;br /&gt;cat /etc/smtprules/qmail-rules.txt | tcprules /etc/tcp.smtp.cdb /tmp/tcp.smtp.tmp&lt;br /&gt;chmod 644 /etc/tcp.smtp*&lt;br /&gt;echo “/etc/tcp.smtp.cdb is reloaded”&lt;br /&gt;;;&lt;br /&gt;help)&lt;br /&gt;cat &amp;lt;&amp;lt;HELP&lt;br /&gt;stop -- stops mail service (smtp connections refused, nothing goes out)&lt;br /&gt;start -- starts mail service (smtp connection accepted, mail can go out)&lt;br /&gt;pause -- temporarily stops mail service (connections accepted, nothing leaves)&lt;br /&gt;cont -- continues paused mail service&lt;br /&gt;stat -- displays status of mail service&lt;br /&gt;cdb -- rebuild the tcpserver cdb file for smtp&lt;br /&gt;restart -- stops and restarts smtp, sends qmail-send a TERM &amp; restarts it&lt;br /&gt;doqueue -- sends qmail-send ALRM, scheduling queued messages for delivery&lt;br /&gt;reload -- sends qmail-send HUP, rereading locals and virtualdomains&lt;br /&gt;queue -- shows status of queue&lt;br /&gt;HELP&lt;br /&gt;;;&lt;br /&gt;*)&lt;br /&gt;echo “Usage: $0 {start|stop|restart|doqueue|reload|stat|pause|cont|cdb|queue|help}”&lt;br /&gt;exit 1&lt;br /&gt;;;&lt;br /&gt;esac&lt;br /&gt;exit 0&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ðến đây có lẽ bạn sẽ thấy là binary &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;svc&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; được dùng rất nhiều trong hồ sơ qmailctl và sẽ thắc mắc các thông số -a, -h, -t, -u.... của binary này có những chức năng nào?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Như đã đề cập ở trên về một số binaries của daemontools và các chức năng của chúng; svc dùng để điều khiển một process được khởi động bởi supervise, binary này cho phép Admin ngưng và tái khởi động một process nào đó. Việc ứng dụng chức năng “tái khởi động một process nào đó” của svc hết sức quan trọng vì nó bảo đảm sự hoạt động liên tục của qmail và các phân bộ của  qmail (nếu không mail sẽ bị bounce và không chuyển gởi được khi một trong những phân bộ của qmail bị ngưng).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Sau đây là bảng tóm gọn các thông số của svc (cho trường hợp bạn cần đào sâu), bạn có thể dùng bảng thông số của svc và đối chiếu với phần script trong hồ sơ qmailctl để hiểu rõ hơn các functions của nó:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Thông số        Chức năng&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;-a  Alarm&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; – Dùng để gởi tín hiệu ALRM đến service&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;-c  Continue&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; – Dùng để gởi tín hiệu CONT đến service&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;-d  Down&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; – Dùng để gởi tín hiệu TERM và CONT đến service (nếu service này đang chạy) và không cho phép supervise tái khởi động service này.&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;-h  Hangup&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; – Dùng để gởi tín hiệu HUP đến service&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;-i  Interrupt&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; – Dùng để gởi tín hiệu INT đến service&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;-k  Kill&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; – Dùng để gởi tín hiệu KILL đến service&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;-o  Once&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; – Dùng để khởi động service nếu service này chưa khởi động, nếu service này ngừng sau đó, once ngăn chặn supervise tái khởi động nó.&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;-p  Pause&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; – Dùng để gởi tín hiệu STOP đến service&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;-t  Terminate&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; – Dùng để gởi tín hiệu TERM đến service&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;-u  Up&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; – Nếu service đang ngưng, thông số này khởi động service&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;-x  Exit&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; – Ðình chỉ supervise ngay sau khi service down.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Có hai cách sắp xếp cho hồ sơ “qmailctl” ở trên tự động chạy khi Linux (Unix) system đi xuyên qua “run level”. Linux và các Unix System V xử dụng init.d thư mục để chứa các shell scripts cho các run level, thông thường thư mục init.d có cấu trúc như:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;/etc/init.d&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; hoặc,&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;/etc/rc.d/init.d&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; tùy theo cách sắp xếp và ứng dụng của mỗi Linux distro và Unix System V.&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;a. Cách “lười” (trên RedHat và một số distro có ứng dụng chkconfig):&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Tạo hồ sơ qmailctl như trên trong /var/qmail/bin (cho tiện)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Làm cho qmailctl “chạy được” và tạo “soft link” từ hồ sơ qmailctl này vào /etc/rc.d/init.d (hoặc /etc/init.d tùy theo) và /usr/bin&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# chmod 755 /var/qmail/bin/qmailctl&lt;br /&gt;# ln -s /var/qmail/bin/qmailctl /etc/rc.d/init.d/qmail&lt;br /&gt;# ln -s /var/qmail/bin/qmailctl /usr/bin&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Chuyển vào thư mục /etc/rc.d/init.d&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# cd /etc/rc.d/init.d&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Chạy lệnh chkconfig để đưa các “soft links” vào đúng các “run level”&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# chkconfig –add qmail&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Nên nhớ phải có phần #chkconfig: - 80 30 và # description: ở phần đầu của qmailctl không thì lệnh chkconfig sẽ không chạy được. 80 và 30 là enable level và disable level của qmail (xem thêm các tài liệu về runlevel trên Sys V)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;b. Cách “cổ điển” (trên tất cả các distro và System V):&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Cách “cổ điển” để tạo ra runlevel cho System V sau đây rất căn bản và thông thường.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Sau khi tạo hồ sơ qmailctl trong /var/qmail/bin và làm nó “chạy được” với chmod như trên phần “lười”, bạn tạo ra các soft link từ qmailctl đến tới từng runlevel như sau:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# ln -s /var/qmail/bin/qmailctl /etc/rc.d/rc0.d/K30qmail&lt;br /&gt;# ln -s /var/qmail/bin/qmailctl /etc/rc.d/rc1.d/K30qmail&lt;br /&gt;# ln -s /var/qmail/bin/qmailctl /etc/rc.d/rc2.d/S80qmail&lt;br /&gt;# ln -s /var/qmail/bin/qmailctl /etc/rc.d/rc3.d/S80qmail&lt;br /&gt;# ln -s /var/qmail/bin/qmailctl /etc/rc.d/rc4.d/S80qmail&lt;br /&gt;# ln -s /var/qmail/bin/qmailctl /etc/rc.d/rc5.d/S80qmail&lt;br /&gt;# ln -s /var/qmail/bin/qmailctl /etc/rc.d/rc6.d/K30qmail&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ở trên cho thấy các symbolic links từ /var/qmail/bin/qmailctl đến mỗi runlevel (của các rcX.d) với chỉ định: qmail ngưng hoạt động ở &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;rc0.d, rc1.d&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;rc6.d&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và hoạt động ở &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;rc2.d, rc3.d, rc4.d&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;rc5.d&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; (ký hiệu &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;K&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; dùng cho &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;Stop&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và ký hiệu &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;S&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; dùng cho &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;Start&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; trong runlevel). Ở đây tôi chọn S80 và K30 dựa trên runlevel (by default) của Sendmail, bạn có thể chọn chỉ số khác thích hợp cho yêu cầu riêng. Tuy nhiên, nên sắp xếp runlevel theo đúng trình tự và ưu tiên của mỗi daemon không thì sẽ tạo ra sự cố cho các daemon của system.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;3.3 Stop Sendmail và link Sendmail&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Có lẽ bạn sẽ tự hỏi tại sao lại có Sendmail ở đây và tại sao phải Stop Sendmail rồi link Sendmail? Câu trả lời như sau: Sendmail gần như là một MTA default cho các Linux Distro cũng như đa số các Unix flavor cho nên cơ hội Sendmail daemon đang chạy và chiếm cứ port 25 trên máy của bạn rất cao. Ðiều này dẫn đến nhiều trục trặc tai quái khi qmail bắt đầu khởi động (cho dù bạn vẫn có thể chỉnh định cho Sendmail và Qmail cùng chạy trên một host nếu sắp xếp cẩn thận). Bước Stop Sendmail và Link Sendmail theo tôi, là một bước hết sức quan trọng và cần thiết. Tất nhiên, nếu bạn không hề có Sendmail trên máy thì bước này không cần phải đi xuyên qua.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;3.3.1 Stop Sendmail:&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Thông thường, Stop Sendmail cách đơn giản nhất là dùng runlevel script trong /etc/rc.d/init.d/sendmail để Stop:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# /etc/rc.d/init.d/sendmail stop&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Cách “dã chiến” là &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;kill&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; process ID nào của Sendmail nếu Sendmail đang chạy (hoặc system của bạn không dùng runlevel hoặc Sendmail được khởi động kiểu “dã chiến”...). Dùng lệnh ps để in ra các process nào của Sendmail:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# ps -ef | grep sendmail&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Sau khi ps cho bạn danh sách các process thuộc Sendmail, bạn chỉ đơn giản “kill”:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# kill PID-of-Sendmail&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Cho an toàn, bạn nên tháo bỏ trọn bộ Sendmail nếu đã quyết định không dùng nó nữa hoặc ít nhất là tháo bỏ các symbolic link cho runlevel của Sendmail trong /etc/rc.d/rcX.d. Ðể tháo bỏ các runlevel theo phương pháp tiện dụng chkconfig (trên RedHat và các distro có ứng dụng chkconfig này):&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# chkconfig –del sendmail&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Ðể tháo bỏ các symbolic links cho runlevel của Sendmail theo kiểu “dã chiến”:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# mv /etc/rc.d/init.d/sendmail /etc/rc.d/init.d/sendmail.old&lt;br /&gt;# rm -f /etc/rc.d/rc0.d/K30sendmail&lt;br /&gt;# rm -f /etc/rc.d/rc1.d/K30sendmail&lt;br /&gt;# rm -f /etc/rc.d/rc2.d/S80sendmail&lt;br /&gt;# rm -f /etc/rc.d/rc3.d/S80sendmail&lt;br /&gt;# rm -f /etc/rc.d/rc4.d/S80sendmail&lt;br /&gt;# rm -f /etc/rc.d/rc5.d/S80sendmail&lt;br /&gt;# rm -f /etc/rc.d/rc6.d/K30sendmail&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Ðể tháo bỏ luôn cả binaries của Sendmail, trên RedHat hoặc distro nào dùng RPM bằng cách:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# rpm -e –nodeps sendmail&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Hoặc đi vào từng thư mục /usr/sbin hoặc /usr/local/sbin (hoặc /usr/lib, /usr/local/lib) để manually rename từng binary thuộc về Sendmail (nếu Sendmail được cài vào máy theo phương thức “compile and build” tổng quát.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;3.3.2 Link Sendmail&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ðã muốn xoá luôn Sendmail vậy sao còn link Sendmail là sao? Có rất nhiều chương trình trên Linux và Unix “gọi” Sendmail để chuyển gởi thông điệp theo “default”. Nếu Sendmail binary bị hoàn toàn tháo gỡ thì không chóng thì chầy bạn sẽ lâm vào nhiều trục trặc bí ẩn :). Cách loại trừ những trục trặc “bí ẩn” có thể xảy ra là dùng phương thức Link Sendmail. Link Sendmail ở đây là link một copy có tên là Sendmail từ binary của Qmail thay vì dùng nguyên bản binary của Sendmail.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Ðổi tên của nguyên bản binary Sendmail:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# mv /usr/sbin/sendmail /usr/sbin/sendmail.old&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# mv /usr/lib/sendmail /usr/lib/sendmail.old&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Link bản Sendmail của Qmail vào các thư mục /usr/sbin và /usr/lib:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# ln -s /var/qmail/bin/sendmail  /usr/lib&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# ln -s /var/qmail/bin/sendmail /usr/sbin&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;3.4 Thư mục “supervise” và các ứng động trong thư mục này&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ðến đây, bạn cần tạo các thư mục và một số hồ sơ “supervise” cho qmailctl làm việc (bạn xem lại qmailctl có rất nhiều phần svc dùng /var/qmail/supervise/qmail-send hoặc /var/qmail/supervise/qmail-smtpd). Các bước kế tiếp rất đơn giản, tuy nhiên bạn nên cẩn thận với các chi tiết không thì sẽ gặp những trục trặc sau này.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ðầu tiên, bạn tạo ra 2 thư mục:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# mkdir -p /var/qmail/supervise/qmail-send/log&lt;br /&gt;# mkdir -p /var/qmail/supervise/qmail-smtpd/log&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Trong đó, thông số -p (parents) dùng để tạo các thư mục từ trên xuống dưới (từ supervise đến qmail-send và log tương tự cho qmail-smtpd và log). Ðiều này có nghĩa trước khi &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;mkdir&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; tạo ra thư mục &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;log&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; bên trong thư mục &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;qmail-send&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;, nó kiểm tra xem thư mục &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;qmail-send&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; có sẵn hay không và tạo ra thư mục này nếu cần. Tương tự nó kiểm tra xem thư mục &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;supervise&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; có sẵn hay không.... (Dùng # mkdir –help để xem thêm chi tiết)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;3.4.1 Thư mục “qmail-send” trong supervise&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Sau khi tạo ra các thư mục /var/qmail/supervise/qmail-send/log như trên, bạn phải đi qua các bước như sau:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Tạo một hồ sơ gọi là &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;run&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; trong /var/qmail/supervise/qmail-send (hồ sơ &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;run&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; nằm trong thư mục qmail-send – chú ý vị trí của các hồ sơ trong các thư mục). Hồ sơ &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;run&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; này có chi tiết như sau:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: courier new;"&gt;#!/bin/sh&lt;br /&gt;exec /var/qmail/rc&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Bạn còn nhớ hồ sơ “rc” ở phần 3.1 không? Ðây chính là nơi “rc” được gọi và thi hành nhiệm vụ trong trọn bộ cơ chế hoạt động của qmail và daemontools. Sau khi tạo ra hồ sơ run này, bạn phải đổi “mod” của nó thành “executable”:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# chmod 755 /var/qmail/supervise/qmail-send/run&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Tạo một hồ sơ khác cũng có tên là &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;run&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; nhưng nằm trong thư mục &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;log&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; của thư mục &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;qmail-send&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;). Hồ sơ &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;run&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; này có trách nhiệm gọi &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;multilog&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; thi hành nhiệm vụ logging của những gì qmail-send gởi đi; nó có chi tiết như sau:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;#!/bin/sh&lt;br /&gt;exec /usr/local/bin/setuidgid qmaill /usr/local/bin/multilog t s5000000000 /var/log/qmail&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Ðừng quan tâm lắm đến các thông số của shell script “run” lúc này. Các chi tiết sẽ đưọc đào sâu thêm trong những phần sau. Nếu bạn quan sát kỹ sẽ thấy mọi bước ăn khớp với nhau từ giai đoạn tạo ra thư mục cho log và thư mục này đến đây được dùng như một thông số trong shell script “run” ở trên. Sau khi tạo ra hồ sơ run này, bạn phải đổi “mod” của nó thành “executable”:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# chmod 755 /var/qmail/supervise/qmail-send/log/run&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;(Còn tiếp)&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37459183-3299642518141965385?l=conmale.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://conmale.blogspot.com/feeds/3299642518141965385/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37459183&amp;postID=3299642518141965385' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/3299642518141965385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/3299642518141965385'/><link rel='alternate' type='text/html' href='http://conmale.blogspot.com/2007/06/qmail-as-mail-gateway-phn-2.html' title='Qmail as a Mail Gateway - Phần 2'/><author><name>conmale</name><uri>http://www.blogger.com/profile/16598933828282382048</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/-2pIWb2iUysc/TzSYz5aVJYI/AAAAAAAAAAQ/BCWx8yVHmbU/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37459183.post-2444069368150291620</id><published>2007-06-25T12:09:00.000+10:00</published><updated>2007-06-25T12:11:09.411+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Qmail as a Mail Gateway - Phần 1</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;1. Giới thiệu về Qmail&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;1.1 Tài liệu dành cho ai?&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tài liệu này dành cho những ai muốn dùng Qmail như một MTA cho hệ thống mail. Ðiều cần thiết là người đọc phải có kiến thức căn bản sử dụng một hệ thống *nix (cách sử dụng các lệnh và cách truy cập / tạo vào các thư mục). Người viết tài liệu không chịu trách nhiệm cho bất cứ hư hại đến máy của người dùng cũng như sự phiền não, bực dọc, mất ngủ .... đến người dùng tài liệu này :)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tài liệu này đào sâu ở mức độ có hạn. Mọi ứng dụng tùy thuộc vào nhu cầu và khả năng thiết lập của người dùng. Qmail không phải là một MTA phức tạp. Tuy nhiên nó mang một số khái niệm điều hành độc lập giữa các thành phần để tạo nên một MTA làm việc hoàn chỉnh, do đó, người đọc nên nghiên cứu kỹ trước khi bắt tay vào việc thiết kế một hệ MTA dùng Qmail.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tài liệu này ứng dụng mô hình qmail làm mail gateway để nhận mail từ Internet và chuyển mail đến một hoặc nhiều mail servers bên trong mạng riêng. Người viết không ứng dụng mô hình qmail như là một mail server phục vụ tất cả các mail protocol khác như IMAP, POP3... vì lý do bảo mật. Có hai điểm tối quan trọng của mô hình mail gateway là:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;Ổn định và hiệu năng:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; qmail có khả năng chuyển nhận hàng triệu thông điệp một ngày (dựa vào tài liệu trên web site của qmail.org). Tuy nhiên, nếu biến nó thành một mail server phục vụ tất cả các mail protocol thì bị giới hạn trong vấn đề kiểm dịch (authentication). Nếu mail server thuộc một mạng dùng hoàn toàn Unix thì giới hạn này có thể khắc phục dễ dàng. Không may trên thực tế hiện nay, không còn nhiều mạng “thuần” Unix hoặc “thuần” một hệ điều hành nào khác. Bởi vậy, qmail hoạt động như một mail gateway chỉ có trách nhiệm chuyển mail đến các mail servers khác (trong giới hạn cho phép domain) mà không phải lo vấn đề authentication, do đó, ngoài tính bảo mật, tính hiệu năng được nâng cao đáng kể.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;-&lt;/span&gt;&lt;b style="font-family: verdana;"&gt;Tính bảo mật:&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; Như đã nêu ra ở trên những khó khăn trong cơ chế quản lý kiểm dịch của một (hoặc nhiều) mạng có đa hệ điều hành không những giảm sút tính hiệu năng mà còn ảnh hưởng lớn đến tính bảo mật. Lý do, quản lý một trung tâm tài nguyên nhân dụng (central user database) dễ dàng và ổn định hơn nhiều user database. Hơn thế, cơ chế Internet &amp;lt;--&amp;gt; Mail Gateway &amp;lt;--&amp;gt; Firewall &amp;lt;--&amp;gt; Internal Mail Servers &amp;lt;--&amp;gt; Users chặc chẽ và an toàn hơn. Ðó là chưa kể ứng dụng kiểm soát / ngăn chặn viruses, trojans và cách loại scripts mang tính phá hoại trên một Unix Mail Gateway trước khi thông điệp được chuyển vào một Mail Server bên trong (Microsoft Exchange hoặc IBM Lotus chẳng hạn). Các ứng dụng cho POP3 hoặc IMAP được thiết lập một cách độc lập trên internal mail servers và người dùng có thể truy cập qua một cơ chế firewalling nào đó.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;1.2 Sơ lược về Qmail&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Qmail được viết bởi Tiến sĩ toán của trường đại học Illinois, Chicago, tiến sĩ Dan Bernstein. Qmail ra đời vào tháng Giêng năm 1996 với một phiên bản Beta 0.70 và sau đó phiên bản Gamma 0.90 được cập nhật vào tháng 8 năm 1996. Phiên bản ổn định 1.0 được ra mắt vào tháng 2 năm 1997. Phiên bản được lưu hành hiện nay là 1.03 được phát hành vào tháng 6 năm 1997.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;1.3 Tại sao dùng Qmail?&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Có rất nhiều MTA trên môi trường *nix hiện nay và mỗi khi nhắc đến MTA chúng ta phải nhắc đến Sendmail. Tuy nhiên, Dan Bernstein viết Qmail vì ông ta thấy rằng Sendmail thừa hưởng nhiều lỗi bảo mật từ các phiên bản trước đây và phần mềm này rất cồng kềnh, cho dù những năm gần đây, nhóm Sendmail không ngừng điều chỉnh và cải tiến phần mềm này để giảm thiểu những yếu điểm. Khi viết Qmail, ngoài ưu tiên cho vấn đề bảo mật, Dan Bernstein chú trọng rất nhiều đến khả năng hoạt động và tính dễ dùng của nó. Qmail mang tính truyền thống của các hoạt trình Unix: mỗi tiểu ứng trình có khả năng đảm đương trọn vẹn một chức năng chuyên biệt và các tiểu ứng trình này có thể chuyền (pipe) sang các tiểu ứng trình khác để đáp ứng các quy trình phức tạp. Bởi thể, Qmail bao gồm nhiều binaries tạo thành một dây chuyền hoạt động. Ðây là một điển hình nặng tính bảo mật và tính hiệu năng trong cơ chế điều hành của một MTA.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;2. Cài đặt Qmail&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;2.1 Cài từ “gói” (RPM) hay từ tar ball?&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Qmail thuộc dạng mở-nguồn nên bạn có thể tải mã nguồn của Qmail về để compile và thiết kế nó cho thích hợp với hệ điều hành của mình. Có một số RPM cho RedHat trên Internet (dùng &lt;/span&gt;&lt;a style="font-family: verdana;" target="_BLANK" href="http://rpmfind.net/"&gt;http://rpmfind.net&lt;/a&gt;&lt;span style="font-family: verdana;"&gt; để tìm). Tuy nhiên, có ít nhiều hạn chế khi dùng RPM và không phải các “gói” này luôn luôn có sẵn cho các hệ điều hành.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;RPM thường buộc người dùng cài đặt binaries vào một nơi trong những thư mục và đôi khi sự ép buộc này không tiện cho cách tổ chức thư mục đã có sẵn của bạn. RPM không giải quyết được các trường hợp bị thiếu hoặc sai “thư viện lệ thuộc” (dependencies). Bởi thế, phương cách compile và build từ mã nguồn xem ra là một phương cách khả thi nhất. Hơn nữa, nó sẽ tạo cơ hội cho bạn hiểu rõ hơn cơ chế làm việc của Qmail sau quá trình cài đặt. Tài liệu này sẽ chỉ chuyên chú vào quy trình compile và build từ mã nguồn.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;2.2 Yêu cầu để cài đặt Qmail&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ðể có thể cài đặt Qmail thành công, sau đây là các yêu cầu tối yếu:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Một C compiler, các thư mục header và các thư viện cho hệ thống lập trình. Nếu bạn dùng trong một phiên bản Linux, compiler của bạn hẳn là gcc.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Có đủ nơi chứa cho quá trình build và các binaries và các tài liệu sau khi Qmail được build. Ổ chứa tuyệt đối cần thiết cho Qmail lưu trữ và xử lý mail trong các điểm “xếp hàng” (mail queues).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Domain name của bạn. Qmail chỉ làm việc (đúng) khi bạn có một domain hợp pháp (fully qualified domain name FQDN). Liên hệ với dịch vụ Internet của bạn cho vấn đề này nếu bạn không rõ.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Qmail được thiết kế như một MTA hạng nặng. Ðiều này có nghĩa máy chạy Qmail phải có băng thông ổn định và rộng đủ để tải và nhận mail. Nếu bạn có dự định thiết lập một MTA xuyên qua modem, có lẽ serialmail là một phần mềm thích hợp hơn (&lt;/span&gt;&lt;a style="font-family: verdana;" target="_BLANK" href="http://cr.yp.to/software/serialmail-0.75.tar.gz"&gt;http://cr.yp.to/software/serialmail-0.75.tar.gz&lt;/a&gt;&lt;span style="font-family: verdana;"&gt;).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;2.3 Những điều cần chuẩn bị&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Qmail không phải là một phần mềm MTA phức tạp. Tuy nhiên, cách an toàn nhất nên thử cài đặt trên một máy tách biệt từ hệ thống mail đang làm việc của bạn và thâu thập kinh nghiệm trước khi cài đặt trên máy chính thức. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Thực ra quá trình compile và build qmail sẽ không ảnh hưởng gì đến hệ thống mail đang làm việc của bạn. Tuy nhiên, bước kiểm nghiệm Qmail sẽ làm gián đoạn hệ thống mail đang có. Ðề nghị trên đơn giản là một cách nhắc nhở mang tính an toàn.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Nếu bạn có dụng ý chuyển đổi (migrate) từ một MTA khác sang Qmail, cũng như bao nhiêu quy trình chuyển đổi khác, giai đoạn hình thành một chiến thuật chuyển đổi (từng bước một) là một điều hết sức cần thiết và giai đoạn “thử” Qmail sẽ giúp bạn hình thành chiến thuật này chính xác hơn và hữu hiệu hơn.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;2.4 Tải mã nguồn từ đâu&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Mã nguồn Qmail có thể được tải về từ: &lt;/span&gt;&lt;a style="font-family: verdana;" target="_BLANK" href="ftp://cr.yp.to/software/qmail-1.03.tar.gz"&gt;ftp://cr.yp.to/software/qmail-1.03.tar.gz&lt;/a&gt;&lt;span style="font-family: verdana;"&gt; hoặc theo đường dẫn của site &lt;/span&gt;&lt;a style="font-family: verdana;" target="_BLANK" href="http://cr.yp.to/software.html"&gt;http://cr.yp.to/software.html&lt;/a&gt;&lt;span style="font-family: verdana;"&gt; (site chính thức của mã nguồn Qmail).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Ngoài mã nguồn của Qmail ở trên, bạn cần thêm ít nhất hai phần mềm phụ nhưng tuyệt đối cần thiết cho Qmail (chi tiết hoạt động của các phần mềm phụ này sẽ được trình bày trong quy trình thiết lập Qmail). Hai phần mềm phụ nói trên là: &lt;/span&gt;&lt;a style="font-family: verdana;" target="_BLANK" href="ftp://cr.yp.to/ucspi-tcp/ucspi-tcp-0.88.tar.gz"&gt;ftp://cr.yp.to/ucspi-tcp/ucspi-tcp-0.88.tar.gz&lt;/a&gt; (cho uscpi-tcp) và &lt;a style="font-family: verdana;" target="_BLANK" href="ftp://cr.yp.to/daemontools/daemontools-0.76.tar.gz"&gt;ftp://cr.yp.to/daemontools/daemontools-0.76.tar.gz&lt;/a&gt;&lt;span style="font-family: verdana;"&gt; (cho daemontols).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;2.4 Từng bước cài đặt&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;2.4.1 Xả nén mã nguồn&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Các bước cài đặt cần chủ quyền root nên trước khi xả nén vào tạo các hồ sơ thư mục, bạn nên chuyển chủ quyền sang super user. Theo quy định chung của System V, các nguồn và binaries do người dùng thêm vào system nên cho vào /usr/local/src, cho nên chúng ta cứ theo vậy mà làm.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- chuyển thành super user:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;myshell$ su&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;(đánh mật mã của root)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- đổi umask thành 022 cho bảo đảm&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# umask 022&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- tạo thư mục /usr/local/src (nếu nó chưa có sẵn)&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# mkdir -p /usr/local/src&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- dời các source của qmail vào trong /usr/local/src&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# mv qmail-1.03.tar.gz ucspi-tcp-0.88.tar.gz  daemontools-0.76.tar.gz /usr/local/src&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- vào thư mục /usr/local/src để xả nén cái gói qmail, uscpi-tcp và daemontools&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# cd /usr/local/src&lt;br /&gt;# gunzip *&lt;br /&gt;# tar -xpvf qmail-1.03.tar&lt;br /&gt;# tar -xpvf ucspi-tcp-0.88.tar&lt;br /&gt;# tar -xpvf  daemontools-0.76.tar &lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;2.4.2 Tạo hồ sơ thư mục&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ðến đây bạn đã có một nhóm thư mục như sau:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;/usr/local/src/qmail-1.03, /usr/loca/src/ucspi-tcp-0.88 và /usr/local/src/admin/daemontools-0.76.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Bước kế tiếp tạo thư mục chủ cho Qmail, đây là nơi trọn bộ binary và configuration cho qmail được cất giữ và điều hành.&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# mkdir /var/qmail&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Tạo thư mục bin trong thư mục chủ của qmail, nơi chứa các binaries&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# mkdir /var/qmail/bin&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Tạo thư mục control trong thư mục chủ của qmail, nơi chứa các hồ sơ chỉnh liệu&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# mkdir /var/qmail/control&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Tạo thư mục alias trong thư mục chủ của qmail, nơi chứa các hồ sơ ảo&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# mkdir /var/qmail/alias&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Tạo thư mục man trong thư mục chủ của qmail, nơi chứa các tài liệu cho qmail&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# mkdir /var/qmail/man&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;2.4.3 Tạo tài khoản nhân dụng và nhóm nhân dụng&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Vấn đề tạo tài khoản nhân dụng và nhóm nhân dụng hết sức quan trọng cho qmail trong vấn đề hoạt động vào bảo mật. Tài khoản nhân dụng cho phép qmail hoạt động trong giới hạn trách nhiệm của nó. Ðiều này có nghĩa, trường hợp qmail bị “hack”, tài khoản nhân dụng của qmail không thể dùng (hoặc rất khó) để xâm nhập hệ thống sâu hơn.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Có một số phương thức khác nhau để tạo tài khoản nhân dụng và nhóm nhân dụng. Nhiều người xử dụng qmail đã tạo ra một số scripts để thực hiện bước này một cách nhanh chóng và dễ dàng. Tuy nhiên ở đây chúng ta nên đi xuyên qua các bước này một cách cụ thể để có thể hiểu sâu hơn vấn đề tài khoản nhân dụng và bảo mật trong quá trình tạo tài khoản nhân dụng.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Tạo nhóm nhân dụng nofiles&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# groupadd nofiles&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Tạo tài khoản nhân dụng cho nhóm nofiles này&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# useradd alias -g nofiles -d /var/qmail/alias -s  /bin/true&lt;br /&gt;# useradd qmaild -g nofiles -d /var/qmail -s /bin/true&lt;br /&gt;# useradd qmaill -g nofiles -d /var/qmail -s /bin/true&lt;br /&gt;# useradd qmailp -g nofiles -d /var/qmail -s /bin/true&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Như các bạn thấy, chuỗi lệnh ở trên là lệnh căn bản tạo tài khoản nhân dụng cho các user &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;alias, qmaild, qmaill và qmailp&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; có cùng một nhóm nhân dụng là &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;nofiles&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Ðặc biệt các lệnh trên không cho những user này một shell nào cả (&lt;/span&gt;&lt;b style="font-family: verdana;"&gt;-s /bin/true&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; – lệnh true thực sự không làm gì cả) vì lý do các user này là các “nhân viên” hoạt động của qmail và chúng không hề cần shell. Một điểm cần nhớ trong quá trình tạo tài khoản nhân dụng: khi “người dùng” không cần một shell để thi hành trách nhiệm thì không nên cho họ một shell. Trường hợp một tài khoản nhân dụng bị hack, tin tặc khó có thể đi sâu hơn nếu tài khoản nhân dụng đó không được phép xử dụng bất cứ một shell nào.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Tương tự, tạo nhóm nhân dụng qmail như sau:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# groupadd qmail&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Tạo tài khoản nhân dụng cho nhóm nhân dụng qmail này:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# useradd qmailq -g qmail -d /var/qmail -s /bin/true&lt;br /&gt;# useradd qmailr -g qmail -d /var/qmail -s /bin/true&lt;br /&gt;# useradd qmails -g qmail -d /var/qmail -s /bin/true&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Một lần nữa, các “người dùng” qmailq, qmailr và qmails thuộc nhóm qmail này không cần shell. Lý do phải tạo các người dùng như trên sẽ được giải thích trong những bước sau.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Bước kế tiếp rất quan trọng. Bước này kiểm nghiệm chủ quyền và nhóm nhân dụng của các “người dùng” vừa tạo ra ở trên.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Dùng &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;vi&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;hoặc bất cứ text editor nào vào /etc/group và viết xuống mã hiệu (GID hay group ID) của nhóm nhân dụng nofiles và qmail. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Ví dụ group nofiles có mã hiệu là 2004 và group qmail là 2005. Bạn dùng vi vào /etc/passwd và kiểm lại xem các entry cho alias, qmaild, qmaill, qmailp, qmailq, qmailr và qmails có đúng nhóm nhân dụng và shell của họ là /bin/true hay không. Những entry này tương tự như:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;alias:*:1005:2004::/var/qmail/alias:/bin/true&lt;br /&gt;qmaild:*:1006:2004::/var/qmail:/bin/true&lt;br /&gt;qmaill:*:1007:2004::/var/qmail:/bin/true&lt;br /&gt;qmailp:*:1008:2004::/var/qmail:/bin/true&lt;br /&gt;qmailq:*:1009:2005::/var/qmail:/bin/true&lt;br /&gt;qmailr:*:1010:2005::/var/qmail:/bin/true&lt;br /&gt;qmails:*:1011:2005::/var/qmail:/bin/true&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Trong các entry ở trên mỗi user có riêng một mã hiệu và thuộc vào nhóm nhân dụng khác nhau.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;2.4.4 Build binaries từ mã nguồn&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ðến đây bạn đã sẵn sàng thực hiện bước compile và build qmail. Các bước build qmail như sau:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- cd vào thư mục chứa mã nguồn của qmail &lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# cd /usr/local/src/qmail-1.03&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;-  Ðánh lệnh make  buộc compiler biên dịch mã nguồn của qmail dựa trên chỉnh định của hồ sơ Makefile &lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# make&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Ðánh các lệnh &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;make setup check&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Ðây là 2 lệnh gom lại thành một.. Lệnh thứ nhất &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;make setup&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; chuyển các binaries đã được build ở trên vào đúng nơi của nó. Lệnh thứ nhì &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;make check&lt;/b&gt; là lệnh dùng để kiểm tra lại thực tính của các hồ sơ và binaries được build.&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# make setup check&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Bước kế tiếp là bước hiệu chỉnh DNS cho qmail. Nếu DNS server (fully qualified) của bạn đã sẵn sàng, bạn chỉ cần chạy lệnh:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# ./config&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Lệnh này kiểm tra DNS server của bạn, nếu không có gì trở ngại nó đặt domain name của bạn vào /var/qmail/control/&lt;/span&gt;&lt;b style="font-family: verdana;"&gt;defaultdomain&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và /var/qmail/control/&lt;/span&gt;&lt;b style="font-family: verdana;"&gt;plusdomain&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; (plusdomain dành cho một binary của qmail “qmail-inject” để thêm vào entry của plusdomain khi cần. Xem thêm ở phần 4: Hồ sơ điều chỉnh của Qmail trong “qmail-control”). Lệnh này cũng thêm vào các entry cần thiết cho /var/qmail/control/&lt;/span&gt;&lt;b style="font-family: verdana;"&gt;locals&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và /var/qmail/control/&lt;/span&gt;&lt;b style="font-family: verdana;"&gt;rcphosts.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Vì một lý do trục trặc nào đó thuộc DNS làm cho lệnh &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;./config&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; ở trên không thể lấy được DNS entry để điều chỉnh các hồ sơ trên, bạn phải dùng lệnh &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;./config-fast&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; để cài các entry cần thiết vào /var/qmail/control/&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Ðánh lệnh ./config-fast với thông số là domain name của bạn&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# ./config-fast mydomain.com&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;mydomain.com phải là một domain name hoàn toàn hợp pháp và đã đăng ký với Internic (xem ở bước 2.2: Yêu cầu để cài đặt qmail ở trên). Lệnh ./config-fast của bước này sẽ cài các entry cần thiết với domain name bạn đã cho (như thông số ở trên); chắc chắn bạn sẽ không bị trở ngại gì trong bước này. Tuy nhiên, những bước sau này bạn sẽ gặp trở ngại &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;nếu như bạn không cung cấp một domain name hợp pháp&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Bước này chỉ buộc ./config-fast cài vào entry bạn cung cấp mà không bảo đảm (không kiểm nghiệm) là domain name đó giá trị hay không.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;2.4.5 Cài ucspi-tcp&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;ucspi-tcp là phần mềm Dr. Dan Bernstein viết với mục đích thay thế cho inet daemon của Unix. Inet daemon được dùng rộng rãi trên các ứng trình Unix và gần đây, xinet ra đời để nâng cao tính năng của inet. Theo Dr Bernstein, phần mềm ucspi-tcp (dùng Unix Client-Server Program Interface cũng của ông) gọn nhẹ, hiệu quả và an toàn hơn inet rất nhiều. Bản thân người viết tài liệu này đã thử cả hai ứng dụng trên xinetd và uscpi-tcp và thấy rõ ưu điểm của ucspi-tcp trên bình diện hiệu năng. Ucspi-tcp được tạo ra với quan tâm bảo mật nên cách xử lý socket giữa client và server rất hiệu quả. Thực tế cho thấy ucspi-tcp ứng hoạt khít khao với qmail.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Ðể compile và build uscpi-tcp, bạn cd vào thư mục uscpi-tcp&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# cd /usr/local/src/ucspi-tcp-0.88&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;-  Ðánh lệnh make  buộc compiler biên dịch mã nguồn của ucspi-tcp dựa trên chỉnh định của hồ sơ Makefile &lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# make&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Ðánh các lệnh &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;make setup check&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Ðây là 2 lệnh gom lại thành một.. Lệnh thứ nhất &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;make setup&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; chuyển các binaries đã được build ở trên vào đúng nơi của nó. Lệnh thứ nhì &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;make check&lt;/b&gt; là lệnh dùng để kiểm tra lại thực tính của các hồ sơ và binaries được build.&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# make setup check&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Nếu quy trình này không bị trở ngại gì, bạn đã compile và build xong ucspi-tcp.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;2.4.6 Cài daemontols&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Daemontools là một phần mềm giúp bạn rất nhiều trong quy trình quản lý và điều hành qmail server. Bạn có thể dùng qmail mà không cần đến daemontools. Tuy nhiên, khi đã dùng qmail nhiều hơn, bạn sẽ khám phá daemontools là một thứ đồ nghề không thể thiếu được.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ðể compile và build daemontools, chỉ đơn giản cd vào thư mục của daemontools-0.76&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# cd /usr/local/src/admin/daemontools-0.76&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Thư mục này có hai thư mục con, bạn không cần vào các thư mục con mà chỉ cần đánh lệnh&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# package/install&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;(Còn tiếp)&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37459183-2444069368150291620?l=conmale.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://conmale.blogspot.com/feeds/2444069368150291620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37459183&amp;postID=2444069368150291620' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/2444069368150291620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/2444069368150291620'/><link rel='alternate' type='text/html' href='http://conmale.blogspot.com/2007/06/qmail-as-mail-gateway-phn-1.html' title='Qmail as a Mail Gateway - Phần 1'/><author><name>conmale</name><uri>http://www.blogger.com/profile/16598933828282382048</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/-2pIWb2iUysc/TzSYz5aVJYI/AAAAAAAAAAQ/BCWx8yVHmbU/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37459183.post-777318610918187443</id><published>2007-06-20T20:03:00.000+10:00</published><updated>2007-06-20T20:04:58.947+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Biên dịch Linux kernel - phần 4 (phần cuối)</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;9. Cài kernel&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Phần này giới thiệu hai cách cài kernel vừa biên dịch và chỉnh định boot loader.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;9.1 Cài qua "make install"&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ít người dùng đến chức năng "make install" này vì một số bản phân phối không có các tiện ích cần thiết để thực hiện trọn vẹn bước này. "make install" tiện lợi và an toàn hơn cài bằng tay vì nó thao tác các bước cần thiết để thiết lập kernel mới trên hệ thống. Các bước này bao gồm quy trình lưu trữ kernel cũ (trong thư mục /boot), copy kernel image mới, copy System.map mới, điều chỉnh boot loader configuration (lilo.conf hoặc grub.conf) và cập nhật boot loader. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Bước "make install" dựa trên hồ sơ Makefile và install.sh, một shell script thuộc thư mục ./arch/$ARCH/boot. Shell script install.sh "gọi" một số shell script khác như /sbin/installkernel và /sbin/new-kernel-pkg, ngoài ra các shell scripts này còn dựa vào một binary có tên là "grubby" để tạo thông tin trong grub.conf nếu bạn dùng GRUB. Các shell scripts "installkernel" và "new-kernel-install" thuộc gói &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;mkinitrd&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; của RedHat, các bản phân phối khác có những ứng dụng tương tự. Nếu bản phân phối bạn dùng không có gói tương tự, bạn phải cài kernel bằng tay (phần 9.2) hoặc tạo các script tương tự để thực hiện bước này. Trong khuôn khổ giới hạn của bài viết, tôi không đi sâu vào vấn đề tạo các script tiện ích.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Để cài Linux kernel mới, bạn chỉ đơn giản chạy lệnh &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;# make install&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; ở chế độ super user từ trong thư mục chứa mã nguồn của Linux kernel. Sau khi hoàn tất bước "make install" bạn nên kiểm tra lại cấu hình của boot loader trên máy và chạy các lệnh tương ứng (nếu cần) để chỉnh định boot loader cho chính xác.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;9.1.1 Đối với GRUB&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ví dụ bạn có hai phiên bản kernel trên máy 2.4.20 (phiên bản đang chạy) và 2.4.26 (phiên bản vừa được biên dịch), sau khi chạy "make install", grub.conf có chi tiết tương tự như sau:&lt;/span&gt;&lt;br /&gt;&lt;code style="font-family: verdana;"&gt;{b}default=1{/b}&lt;br /&gt;timeout=20&lt;br /&gt;splashimage=(hd0,0)/boot/grub/splash.xpm.gz&lt;br /&gt;&lt;br /&gt;title Linux (2.4.26)&lt;br /&gt;    root (hd0,0)&lt;br /&gt;    kernel /boot/vmlinuz-2.4.26 ro root=/dev/hda1&lt;br /&gt;    initrd=/boot/initrd-2.4.26.img&lt;br /&gt;&lt;br /&gt;title Linux (2.4.20)&lt;br /&gt;    root (hd0,0)&lt;br /&gt;    kernel /boot/vmlinuz-2.4.20 ro root=/dev/hda1&lt;br /&gt;    initrd=/boot/initrd-2.4.20.img&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- chi tiết cần chú ý là biến &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;default&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Trong ví dụ trên, bạn có hai kernel trong cấu hình GRUB cho các phiên bản 2.4.26 và 2.4.20. Nếu bạn muốn boot kernel 2.4.26 theo mặc định thì giá trị của &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;default&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; phải là 0 (grub đếm thứ tự các kernel từ giá trị 0, không phải từ giá trị 1). Khi chạy "make install", các tiện ích của "install" tự động đưa vào các chi tiết thuộc kernel mới vào cấu hình GRUB. Tuy nhiên, giá trị &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;default&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; vẫn giữ ở giá trị chỉ định cho kernel hiện đang hoạt động trên máy. Bạn cần chỉnh giá trị này để buộc boot loader tải lên phiên bản kernel mới. Một chi tiết hết sức quan trọng bạn cần chú ý là giá trị &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;root (hdX,Y)&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Nếu GRUB đã được cài trong lúc cài đặt hệ thống từ CD và đã hoạt động hoàn chỉnh, bạn không nên thay đổi giá trị này. Giá trị này chỉ cần thay đổi nếu bạn thêm đĩa cứng và thay đổi các partitions trên máy.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- sau khi chỉnh định và lưu trữ grub.conf thích hợp, bạn chỉ cần tái khởi động máy. Nếu bạn dùng GRUB làm boot loader thì công tác tái biên dịch nhân Linux hoàn thành ở đây. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- giải pháp phòng bị trường hợp không thể boot vào kernel mới rất đơn giản nếu dùng GRUB làm boot loader. Bạn chỉ cần thêm một dòng &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;fallback 1&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; vào cấu hình grub.conf là đủ. Chỉnh định này cho GRUB boot loader biết nếu dùng "default=0" để boot kernel mới nhất (2.4.26 trong ví dụ này) nhưng không thành công vì lý do nào đó thì thử boot lại với kernel cũ hơn (2.4.20). Xem thêm ở phần 10 nếu không thể boot được vào Linux vì boot loader bị hỏng.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;9.1.2 Đối với LILO&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ví dụ bạn có hai phiên bản kernel trên máy 2.4.20 (phiên bản đang chạy) và 2.4.26 (phiên bản vừa được biên dịch), sau khi chạy "make install", lilo.conf có chi tiết tương tự như sau:&lt;/span&gt;&lt;br /&gt;&lt;code style="font-family: verdana;"&gt;prompt&lt;br /&gt;timeout=50&lt;br /&gt;{b}default=linux{/b}&lt;br /&gt;boot=/dev/hda&lt;br /&gt;map=/boot/map&lt;br /&gt;install=/boot/boot.b&lt;br /&gt;message=/boot/message&lt;br /&gt;&lt;br /&gt;image=/boot/vmlinuz-2.4.20&lt;br /&gt;initrd=/boot/initrd-2.4.20.img&lt;br /&gt;root=/dev/hda1&lt;br /&gt;label=linux-2.4.20&lt;br /&gt;read-only&lt;br /&gt;        &lt;br /&gt;image=/boot/vmlinuz&lt;br /&gt;initrd=/boot/initrd-2.4.26.img&lt;br /&gt;root=/dev/hda1&lt;br /&gt;{b}label=linux{/b}&lt;br /&gt;read-only&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- chi tiết cần chú ý là biến &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;default&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Trong ví dụ trên, bạn có hai kernel trong cấu hình LILO cho các phiên bản 2.4.26 và 2.4.20. Nếu bạn muốn boot kernel 2.4.26 thì giá trị của &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;default&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; phải là giá trị &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;label&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; thuộc kernel nào bạn muốn dùng. Trong trường hợp này, label có giá trị là &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;linux&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; chỉ định cho kernel 2.4.26. Khi chạy "make install", các tiện ích của "install" đưa vào các chi tiết của kernel mới vào cấu hình LILO. Ở đây &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;vmlinuz&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; là symbolic link của hồ sơ &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;vmlinuz-2.4.26&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Bạn nên kiểm tra lại giá trị &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;default&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; để bảo đảm boot loader sẽ tải kernel vừa biên dịch khi boot.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- sau khi chỉnh định và lưu trữ lilo.conf theo ý muốn, bạn phải chạy lệnh:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# /sbin/lilo&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và chú ý trường hợp hệ thống báo lỗi trong bước cài lilo làm boot loader. Nếu có, điều chỉnh cho chính xác và thực hiện lại lệnh trên. Với ví dụ trên, bạn sẽ được báo kết quả trên console tương tự như:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Added linux*&lt;br /&gt;Added linux-2.4.20&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Giá trị nào đi kèm với dấu hoa thị (*) chỉ định cho kernel được boot theo mặc định.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- với LILO, giải pháp đơn giản nhất phòng bị trường hợp không thể boot vào kernel mới mang tính tạm thời. Trước khi tái khởi động máy dùng lệnh như sau:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# /sbin/lilo -R linux&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;rồi chạy&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# reboot&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Nên nhớ lệnh trên được đưa ra như một ví dụ cho kernel 2.4.20 và 2.4.26 với cấu hình boot loader như trên, bạn phải điều chỉnh đúng phiên bản kernel bạn đang biên dịch. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Lệnh thứ nhất cho LILO biết lần kế tiếp máy tái khởi động thì thử dùng kernel 2.4.26. Nếu không thành công cũng không chỉnh định cho kernel 2.4.26 làm kernel boot theo mặc định và lần boot kế tiếp sẽ dùng kernel 2.4.20 (kernel này chắc chắn phải làm việc được vì nó đã dùng để biên dịch kernel 2.4.26).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Lệnh thứ nhì chỉ đơn giản ra lệnh cho máy tái khởi động.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Nếu dùng lệnh "/sbin/lilo -R linux-x.xx.xx" và boot vào kernel mới thành công thì sau khi boot vào, bạn cần chỉnh định cho kernel x.xx.xx làm mặc định rồi mới chạy "/sbin/lilo -v" như đã nói ở trên (trong phần biến "default" của lilo.conf).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;9.2 Cài qua các bước bằng tay&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Các bước cài "bằng tay" tương tự như các bước "make install" ở trên nhưng được thao tác "bằng tay". Thật ra quy trình này rất đơn giản, điều bạn cần lưu ý là phải thực hiện chính xác để tránh những trở ngại trong bước này và trong giai đoạn boot vào kernel mới.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;9.2.1 Tạo initrd&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Trường hợp bạn biên dịch các drivers quan trọng ở dạng modules có liên hệ đến quy trình boot của Linux (như SCSI driver, RAID driver, các loại filesystem mà root filesystem dùng như ext3, jbd...) thì chắc chắn bạn phải cần đến initrd (INITial Ram Disk). Mục đích chính của initrd là phương tiện tải sẵn các driver cần thiết cho kernel trong quá trình boot. Nếu không muốn dùng initrd, bạn &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;phải&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; biên dịch các driver trực tiếp vào kernel (hay còn gọi là static compile). Nên chú ý một số bản phân phối Linux không dùng initrd, họ khuyến khích biên dịch các driver liên hệ đến quy trình boot trực tiếp vào kernel. Muốn tham khảo thêm chi tiết về RAM disk cho trường hợp này, xem &amp;lt;KERNEL_SRC&amp;gt;/Documentation/ramdisk.txt.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Quy trình tạo initrd rất đơn giản, chỉ cần chạy lệnh:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# /sbin/mkinitrd /boot/initrd-&amp;lt;KERNEL_VERSION&amp;gt;.img &amp;lt;KERNEL_VERSION&amp;gt;&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;, trong đó:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Tham số thứ nhất &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;/boot/initrd-&amp;lt;KERNEL_VERSION&amp;gt;.img&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; chỉ định cho hồ sơ và thư mục chứa hồ sơ initrd. Thông thường initrd của kernel được chứa trong thư mục /boot cùng với các thông tin và hồ sơ khác cần thiết cho quy trình boot.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Tham số &amp;lt;KERNEL_VERSION&amp;gt; thứ nhì chính là kernel nào bạn muốn tạo initrd cho nó. Tất nhiên thư mục chứa các modules cho kernel version này &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;phải&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; hiện hữu ở /lib/modules/, nếu không bạn sẽ được system báo lỗi.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tùy bản phân phối, &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;mkinitrd&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; đòi hỏi thêm các thông số cụ thể để chỉ đường dẫn đến kernel. Nếu gặp trở ngại trong bước tạo &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;mkinitrd&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; bạn nên tham khảo tài liệu cụ thể cho bản phân phối mình đang dùng hoặc tối thiểu là xem &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;man mkinitrd&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và tài liệu &amp;lt;KERNEL_SRC&amp;gt;/Documentation/initrd.txt để xem thêm các thông tin cần thiết.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Một điểm đáng chú ý là từ kernel 2.5.x (development kernel) trở đi, &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;initramfs&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; được phát triển với mục đích hỗ trợ và sẽ đi đến chỗ thay thế initrd (init ram disk). Ưu điểm nổi bật của initramfs là nó có thể chứa các bộ lưu trữ ở dạng cpio "newc" hoặc "crc" (được nén hoặc không được nén). initramfs cho đến nay chưa phổ biến và ứng dụng rộng rãi trên các bản phân phối Linux. Tuy nhiên, hướng phát triển và ứng dụng initramfs có vẻ đầy hứa hẹn.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;9.2.2 Copy kernel và System.map&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Sau khi hoàn thành bước "make modules_install" (phần 8.2), lúc này bạn đã có trọn bộ các bộ phận cần thiết cho kernel mới bao gồm kernel image và các modules thuộc kernel này.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- copy bzImage từ &amp;lt;KERNEL_SRC&amp;gt;/arch/i386/boot/ đến thư mục /boot, ví dụ:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# cp /usr/src/linux-2.4.26/arch/i386/boot/bzImage /boot/bzImage-2.4.26&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;install script của RedHat và một số phân phối khác bao gồm bước copy bzImage thành vmlinuz, bạn có thể thực hiện (hay không tùy ý, bước này tương tự như bước ở trên) như sau:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# cp /usr/src/linux-2.4.26/arch/i386/boot/bzImage /boot/vmlinuz-2.4.26&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;kế tiếp là xoá symbolic link cũ (nếu có) của vmlinuz trong thư mục /boot:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# rm -f /boot/vmlinuz&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;và sau đó tạo symbolic link mới cho vmlinuz-2.4.26 thành:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# ln -s /boot/vmlinuz-2.4.26 /boot/vmlinuz&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tất nhiên bạn phải điều chỉnh lại cấu hình boot loader để thích ứng với cách gọi "bzImage" hoặc "vmlinuz" này cho giá trị &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;image&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; (trong lilo.conf) hoặc giá trị &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;kernel&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; (trong grub.conf). Cách dùng và cách gọi &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;bzImage&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;vmlinuz&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; tạo khá nhiều bối rối cho người dùng Linux khi tiếp cận quy trình biên dịch kernel. Một số bản phân phối Linux dùng &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;bzImage&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;, một số khác lại dùng &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;vmlinuz&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;. Dù gì đi chăng nữa, đây cũng chỉ là cách dùng và cách gọi; bạn nên dùng theo cách bản phân phối Linux nào có trên máy. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- phần còn lại là bước copy hồ sơ System.map:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# cp /usr/src/linux-2.4.26/System.map-2.4.26 /boot/System.map-2.4.26&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;kế tiếp là xoá symbolic link cũ của System.map trong thư mục /boot:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# rm -f /boot/System.map&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;và sau đó, tạo symbolic link mới cho System.map:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# ln -s /boot/System.map-2.4.26 /boot/System.map&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;9.2.3. Chỉnh bootloader config&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;9.2.3.1 Nếu bootloader là GRUB&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ví dụ bạn có hai phiên bản kernel trên máy 2.4.20 (phiên bản đang chạy) và 2.4.26 (phiên bản vừa được biên dịch) thì grub.conf tương tự như sau:&lt;/span&gt;&lt;br /&gt;&lt;code style="font-family: verdana;"&gt;default=0&lt;br /&gt;timeout=20&lt;br /&gt;splashimage=(hd0,0)/boot/grub/splash.xpm.gz&lt;br /&gt;title Linux (2.4.20)&lt;br /&gt;    root (hd0,0)&lt;br /&gt;    kernel /boot/vmlinuz-2.4.20 ro root=/dev/hda1&lt;br /&gt;    initrd=/boot/initrd-2.4.20.img&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Chỉnh thành:&lt;/span&gt;&lt;br /&gt;&lt;code style="font-family: verdana;"&gt;default=0&lt;br /&gt;timeout=20&lt;br /&gt;splashimage=(hd0,0)/boot/grub/splash.xpm.gz&lt;br /&gt;&lt;br /&gt;title Linux (2.4.26)&lt;br /&gt;    root (hd0,0)&lt;br /&gt;    kernel /boot/vmlinuz ro root=/dev/hda1&lt;br /&gt;    initrd=/boot/initrd-2.4.26.img&lt;br /&gt;&lt;br /&gt;title Linux (2.4.20)&lt;br /&gt;    root (hd0,0)&lt;br /&gt;    kernel /boot/vmlinuz-2.4.20 ro root=/dev/hda1&lt;br /&gt;    initrd=/boot/initrd-2.4.20.img&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Sau khi đã lưu trữ (save) cấu hình của /etc/grub.conf ở trên (/etc/grub.conf là symbolic link đến /boot/grub/menu.1st) và tái khởi động máy để bắt đầu dùng kernel vừa được biên dịch. Nếu bạn dùng GRUB làm boot loader thì công tác tái biên dịch nhân Linux hoàn thành ở đây. Nên lưu ý trong ví dụ này, tôi dùng &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;vmlinuz&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; thay vì dùng &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;bzImage&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;, bạn nên chọn lựa theo ý và điều chỉnh cho phù hợp trong grub.conf.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Đối với giải pháp phòng bị trường hợp không thể dùng GRUB để boot vào kernel mới, xem chi tiết ở phần 9.1.1 ở trên.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;9.2.3.2 Nếu bootloader là LILO&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Ví dụ bạn có hai phiên bản kernel trên máy 2.4.20 (phiên bản đang chạy) và 2.4.26 (phiên bản vừa được biên dịch) thì lilo.conf tương tự như sau:&lt;/span&gt;&lt;br /&gt;&lt;code style="font-family: verdana;"&gt;prompt&lt;br /&gt;timeout=50&lt;br /&gt;default=linux&lt;br /&gt;boot=/dev/hda&lt;br /&gt;map=/boot/map&lt;br /&gt;install=/boot/boot.b&lt;br /&gt;message=/boot/message&lt;br /&gt;&lt;br /&gt;image=/boot/vmlinuz&lt;br /&gt;initrd=/boot/initrd-2.4.20.img&lt;br /&gt;root=/dev/hda1&lt;br /&gt;label=linux&lt;br /&gt;read-only&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Chỉnh /etc/lilo.conf để cài kernel mới (2.4.26 cho ví dụ ở đây), bạn có /etc/lilo.conf như sau:&lt;/span&gt;&lt;br /&gt;&lt;code style="font-family: verdana;"&gt;prompt&lt;br /&gt;timeout=50&lt;br /&gt;{b}default=linux{/b}&lt;br /&gt;boot=/dev/hda&lt;br /&gt;map=/boot/map&lt;br /&gt;install=/boot/boot.b&lt;br /&gt;message=/boot/message&lt;br /&gt;&lt;br /&gt;image=/boot/vmlinuz-2.4.20&lt;br /&gt;initrd=/boot/initrd-2.4.20.img&lt;br /&gt;root=/dev/hda1&lt;br /&gt;{b}label=linux-2.4.20{/b}&lt;br /&gt;read-only&lt;br /&gt;        &lt;br /&gt;image=/boot/vmlinuz&lt;br /&gt;initrd=/boot/initrd-2.4.26.img&lt;br /&gt;root=/dev/hda1&lt;br /&gt;{b}label=linux{/b}&lt;br /&gt;read-only&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Sau khi đã lưu trữ (save) cấu hình của /etc/lilo.conf ở trên, chạy lệnh:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# /sbin/lilo&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; để đăng ký kernel mới cho LILO boot loader.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Đối với giải pháp phòng bị trường hợp không thể dùng LILO để boot vào kernel mới, xem chi tiết ở phần 9.1.2 ở trên.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;10. Tái khởi động máy và chỉnh lý nếu gặp trục trặc&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tới đây, bạn cần tái khởi động máy để boot vào kernel mới. Nếu không có gì trở ngại, máy sẽ boot vào Linux bình thường. Bạn có thể kiểm lại xem kernel mình đang chạy có đúng phiên bản vừa được biên dịch hay không bằng cách chạy:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ uname -r&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;hoặc,&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ cat /proc/version&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Nếu kết quả báo phiên bản kernel cũ thì có nghĩa boot loader (LILO hoặc GRUB) đã không boot kernel vừa được biên dịch. Bạn nên kiểm tra lại boot configuration (lilo.conf hoặc grub.conf) cho đúng theo chi tiết đã nêu ở trên.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;10.1 Bị treo khi bootloader đang boot vào linux&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Trở ngại trong giai đoạn boot loader chuẩn bị boot vào Linux thông thường do cấu hình boot loader ấn định không đúng và boot loader được cài lên không đúng boot partition hoặc MBR bị hỏng (hiếm thấy trong quá trình tái biên dịch và cài kernel mới nếu thực hiện đúng quy cách). Trong trường hợp này, bạn phải:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- dùng đến đĩa mềm "cấp cứu" được tạo ở phần 6.1 để boot vào Linux&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- Đến giai đoạn này bạn hẳn phải biết vị trí của root partition (/) trên đĩa cứng để mount partition của đĩa cứng:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# mount /dev/hdXy /mount/point/somewhere&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;, trong đó &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;X&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; là ví trí đĩa cứng trên máy, &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;y&lt;/b&gt; là vị trị root partition trên đĩa cứng này.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- đổi root (chroot) trở thành root partition của đĩa cứng:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# chroot /mount/point/somewhere&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;, trong đó &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;/mount/point/somewhere&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; là nơi đĩa cứng của bạn được mount. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- kiểm tra lại cấu hình của boot loader và cài lại boot loader cho máy (xem phần 9.1.1 hoặc 9.1.2 tùy theo boot loader bạn dùng là GRUB hay LILO). Điểm cần chú ý ở đây cho GRUB boot loader là bạn &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;phải&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; chạy lệnh:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# /sbin/grub-install /dev/hdX&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;, trong đó &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;/dev/hdX&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; là disk nào chứa MBR cho hệ thống (thường là đĩa đầu tiên trên máy - Primary Master). Lệnh trên sẽ tái thiết lập boot record và loại bỏ các trường hợp MBR bị hỏng. Tương tự cho LILO, bạn phải chạy lệnh:&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# /sbin/lilo&lt;/b&gt;&lt;span style="font-family: verdana;"&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;10.2 Bị treo trong quá trình kernel được load&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Nếu bạn vướng vào các trở ngại trong giai đoạn kernel đang được tải lên thông thường là do các drivers tối cần thiết để mount filesystems trên máy bị thiếu. Giả sử bạn dùng ext3 cho root partition (/) chứa kernel. Để có thể mount root partition này, ext3 module phải được biên dịch và initrd phải tải module này lên. Tương tự ứng dụng cho các trường hợp dùng filesystem khác và cũng thiếu module. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Trong trường hợp này, bạn cần ghi xuống phần lỗi được báo trong khi boot vào kernel mới để xác định lỗi này thuộc phần nào của cấu hình biên dịch nhân Linux và từ đó điều chỉnh lại và tái biên dịch lại cho thích ứng. Nói một cách tổng quát, bạn phải:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- tái khởi động lại máy và boot vào phiên bản cũ của kernel (hoặc boot loader sẽ boot vào phiên bản cũ của kernel nếu bạn dùng biện pháp trù bị đã được đề cập ở phần 9.1.1 và 9.1.2 ở trên)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- chọn lựa và chỉnh định cấu hình biên dịch nhân Linux lại (xem phần 7.2.2 để tránh lặp lại bước lựa chọn cấu hình một cách không cần thiết). &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- thực hiện lại các bước đã nêu ra trong phần 8 và 9 ở trên&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;11. Vá và biên dịch kernel&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Mã nguồn của Linux kernel thường được "vá" rồi tái biên dịch nhiều hơn là được biên dịch từ trọn bộ mã nguồn tải về từ kernel.org nếu bạn đã quen thuộc với quy trình tái biên dịch hoặc bạn có nhu cầu phải cập nhập kernel của máy thường xuyên. Tại sao lại cần "vá"? Mã nguồn của Linux kernel cần được vá vì các lý do thường gặp như sau:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- mã nguồn của Linux kernel được cập nhật. Bạn đã có sẵn mã nguồn của Linux kernel (cũ hơn) trên máy. Muốn nâng cấp phiên bản của Linux kernel, bạn chỉ cần tải các "miếng vá" về để vá (thay vì phải tải trọn bộ mã nguồn của Linux kernel cho phiên bản mới).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;- một số "drivers" được cập nhật. Để xử dụng các driver mới này (và các drivers này cần được biên dịch để nối với các thư viện hiện hành trên máy), bạn chỉ cần tải các "miếng vá" của những drivers này để vá Linux kernel và tái biên dịch chúng.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;11.1 Các điểm quan trọng trước khi vá&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tương tự như phần 6.2, 6.3 và 6.4 ở trên, quy trình tải các miếng vá (patch) cho Linux kernel y hệt như tải trọn bộ gói mã nguồn của Linux kernel. Điểm khác biệt là bạn phải tải các hồ sơ khởi đầu bằng &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;patch&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và chọn cho đúng các patch cần thiết cho kernel cần được patch.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Điểm tối yếu cần ghi nhớ là khi vá mã nguồn của Linux kernel, bạn phải vá &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;đúng thứ tự và đầy đủ các miếng vá&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; cho đến đúng phiên bản cần có. Ví dụ, bạn đang có phiên bản kernel là 2.4.20 trên máy và bạn muốn tái biên dịch phiên bản kernel của máy trở thành 2.4.26. Thay vì tải trọn bộ mã nguồn của kernel 2.4.26 và biên dịch lại (như đã trình bày trong suốt bài viết này), bạn có thể tải các bản vá 2.4.21, 2.4.22, 2.4.23, 2.4.24, 2.4.25 và 2.4.26 về máy. Tổng cộng dung lượng các bản vá này chỉ là một phần rất nhỏ so với trọn bộ gói mã nguồn 2.4.26. Tất nhiên bạn đã có mã nguồn của kernel 2.4.20 trên máy không thì không thể vá được.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;11.2 Tải, xả và vá&lt;/b&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Các miếng vá thường được nén ở hai dạng: &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;.gz&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; hoặc &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;.bz2&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; như gói mã nguồn. Bạn có thể tùy chọn và có thể tải các miếng vá này về bất cứ nơi nào trên máy. Sau khi tải chúng về, bạn có thể thực hiện quy trình tương tự như sau:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;i style="font-family: verdana;"&gt;giả định các bản vá được nén ở dạng .bz2, nơi chứa mã nguồn của Linux kernel ở /usr/src và thực tính của các patch này đã được kiểm tra. Trong ví dụ này, giả định phiên bản đang dùng trên máy là 2.4.20 và phiên bản cần được vá sẽ là 2.4.26&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;a)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;# chuyển vào thư mục /usr/src&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ cd /usr/src&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;b)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;# xả nén các patch ở dạng .bz2 vào thư mục /usr/src. Lặp lại cho đến khi xả hết các patch cần được vá&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ tar xfvj /path/to/patch/patch-x.xx.xx ./&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;c)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;# dọn dẹp sạch sẽ mã nguồn kernel hiện có trên máy, giả định phiên bản mã nguồn hiện có là 2.4.20&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;cd ./kernel-2.4.20&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;make mrproper&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;d)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;# lưu một bản mã nguồn kernel 2.4.20 trong thư mục /usr/src phòng bị cho sự cố trong quá trình vá (nếu bạn không lưu một bản mã nguồn nguyên thủy của kernel 2.4.20 trên máy, hoặc bản mã nguồn 2.4.20 này cũng đã được vá trước đây)&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;tar cvf ../linux-2.4.20.tar ./&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;e)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;# vá các miếng vá theo đúng thứ tự và theo dõi bất cứ lỗi nào được báo&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ patch -p1 &amp;lt; ../patch-2.4.21&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ patch -p1 &amp;lt; ../patch-2.4.22&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ patch -p1 &amp;lt; ../patch-2.4.23&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ patch -p1 &amp;lt; ../patch-2.4.24&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ patch -p1 &amp;lt; ../patch-2.4.25&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ patch -p1 &amp;lt; ../patch-2.4.26&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;hoặc thực hiện kiểu "lười" như sau:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;# tạo một biến PATCH tạm thời chứa tên các patch cần patch theo đúng thứ tự, tách rời bằng phím trống (space)&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ export PATCH="patch-2.4.21 patch-2.4.22 patch-2.4.23 patch-2.4.24 patch-2.4.25 patch-2.4.26"&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;# chạy vòng lặp&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ for item in $PATCH; do patch -p1 &amp;lt; ../$item; done&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Nếu trong khi vá không có gì trở ngại, bạn sẽ thấy các thông tin tương tự:&lt;/span&gt;&lt;br /&gt;&lt;code style="font-family: verdana;"&gt;patching file xxx&lt;br /&gt;patching file yyy&lt;br /&gt;....&lt;/code&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;cho đến khi kết thúc.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Nếu trong khi vá bị báo lỗi, bạn phải ngưng bước vá (ctrl-C) và kiểm tra xem bạn có dùng &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;đúng bản vá&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và thực hiện các bản vá &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;đúng thứ tự&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; phiên bản hay không. Không nên tiếp tục với bước vá khi gặp lỗi vì chắc chắn bạn sẽ gặp trở ngại trong giai đoạn biên dịch sau này. Để tránh các trở ngại về sau, nếu bị báo lỗi trong khi vá, cách tốt nhất bạn nên xoá trọn bộ thư mục chứa mã nguồn của Linux kernel (đang được vá và bị lỗi) và xả gói mã nguồn nguyên thủy hoặc gói bạn vừa lưu trữ ở trên rồi thử lại.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;f)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;# xoá thư mục chứa mã nguồn vừa vá và bị trục trặc, thư mục linux-2.4.20 được dùng như một ví dụ ở đây&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ cd /usr/src&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ rm -rf ./linux-2.4.20&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;g)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;# xả gói mã nguồn được lưu trữ ở trên&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ tar xvf linux-2.4.20&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ cd ./linux-2.4.20&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;và sau đó lặp lại bước vá (bước e) &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;theo đúng thứ tự&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; các miếng và.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Sau khi vá thành công, bạn &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;nên&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; thực hiện hai bước kế tiếp như sau trước khi bắt tay vào việc chuẩn bị cấu hình biên dịch nhân Linux và biên dịch mã nguồn:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;h)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;# đổi tên thư mục chứa mã nguồn cho đúng phiên bản đã được vá (giúp bạn nhận diện phiên bản của mã nguồn đang có trên máy đã được vá tới phiên bản nào)&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ cd /usr/src&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ mv ./linux-2.4.20 ./linux-2.4.26&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;i)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;# chỉnh giá trị "VERSION" trong Makefile chính của mã nguồn Linux. Thư mục chứa mã nguồn lúc này đã được đổi tên thành linux-2.4.26&lt;/span&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ vi ./linux-2.4.26/Makefile&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Vài dòng đầu của hồ sơ Makefile này chứa các thông tin tương tự như sau (nếu mã nguồn của phiên bản 2.4.20 được xả từ gói mã nguồn nguyên thủy):&lt;/span&gt;&lt;br /&gt;&lt;code style="font-family: verdana;"&gt;VERSION = 2&lt;br /&gt;PATCHLEVEL = 4&lt;br /&gt;SUBLEVEL = 20&lt;br /&gt;EXTRAVERSION =&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Bạn cần đổi giá trị SUBLEVEL thành &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;26&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; và lưu hồ sơ Makefile này (cho ví dụ này, hoặc bất cứ phiên bản nào bạn đã vá tới - xem thêm chi tiết về quy định phiên bản Linux kernel ở phần 3). Giá trị phiên bản &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;2.6.26&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; lấy từ hồ sơ Makefile sẽ được dùng trong quá trình biên dịch và cài đặt kernel về sau. Nếu bạn không điều chỉnh giá trị "VERSION" ở bước này, bước cài kernel về sau sẽ &lt;/span&gt;&lt;b style="font-family: verdana;"&gt;viết chồng&lt;/b&gt;&lt;span style="font-family: verdana;"&gt; lên kernel 2.4.20 đang có trên máy. Nói về mặt kỹ thuật việc viết chồng lên  không có gì trở ngại. Tuy nhiên, nếu bạn gặp trục trặc sau khi đã biên dịch kernel nhưng không boot vào được thì sự thể sẽ rất phức tạp vì bạn không còn bản kernel chạy được trên máy.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;Tới đây bạn đã thực hiện thành công bước vá mã nguồn Linux kernel và các bước phòng bị cần thiết. Bạn có thể tiếp tục với công việc tái biên dịch Linux kernel như đã nói trên.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: verdana;"&gt;&amp;lt;hết&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37459183-777318610918187443?l=conmale.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://conmale.blogspot.com/feeds/777318610918187443/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37459183&amp;postID=777318610918187443' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/777318610918187443'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/777318610918187443'/><link rel='alternate' type='text/html' href='http://conmale.blogspot.com/2007/06/bin-dch-linux-kernel-phn-4-phn-cui.html' title='Biên dịch Linux kernel - phần 4 (phần cuối)'/><author><name>conmale</name><uri>http://www.blogger.com/profile/16598933828282382048</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/-2pIWb2iUysc/TzSYz5aVJYI/AAAAAAAAAAQ/BCWx8yVHmbU/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37459183.post-7706525399598352158</id><published>2007-06-20T15:19:00.000+10:00</published><updated>2007-06-20T20:00:15.066+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Biên dịch Linux kernel - phần 3</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;7.2 Điều chỉnh cấu hình biên dịch nhân Linux&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Vậy, để điều chỉnh các chọn lựa cho một cấu hình biên dịch nhân Linux, có một số cách thực hiện chuyện này.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;7.2.1 Các "config" tools&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Như đã đề cập ở phần 6.5, mặc định cấu hình biên dịch nhân nằm ở ./arch/i386/defconfig. Khi khởi động một "config" tool nó sẽ tự động đọc và dùng nội dung của config mặc định này trước khi bạn chỉnh sửa theo ý.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Để chỉnh cấu hình biên dịch nhân Linux, chuyển vào thư mục chứa mã nguồn của kernel (đã xả nén):&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ cd /usr/src/linux-2.4.26&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; (ví dụ này dùng kernel 2.4.26 - xem lại phần xả nén ở phần 6.4)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;và việc đầu tiên &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;rất nên làm&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; đó là chạy lệnh:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ make mrproper&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Không kể bạn dùng bản phân phối Linux nào và phiên bản Linux kernel nào, bạn nên chạy lệnh này trước khi thực hiện quy trình tái biên dịch kernel. Target "mrproper" này dùng để xoá hết tất cả những gì còn "vất vưởng" trong các cây chứa mã nguồn của Linux kernel để nắm chắc mã nguồn trước khi được biên dịch phải ở tình trạng "sạch sẽ".&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Có ba phương tiện "config" phổ biến có thể dùng để chỉnh cấu hình biên dịch nhân Linux. Sau khi chuyển vào thư mục /usr/src/linux-2.4.26, bạn có thể chọn một trong ba cách:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make config&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make menuconfig&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make xconfig&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Trong đó,&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make config&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; là phương tiện đơn giản nhất và không đòi hỏi thêm bất cứ thư viện nào khác để chạy công cụ này. &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make config&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; sẽ tạo ra một loạt câu hỏi (ở dạng prompt) và sau khi nhận được câu trả lời của bạn (Y, N, M như đã nói ở trên sau khi bạn nhấn phím Enter, xác nhận câu trả lời của mình), nó sẽ hình thành một cấu hình biên dịch nhân Linux. Nhược điểm của loại config này ở chỗ, nếu bạn lỡ trả lời sai (chọn Y, N hoặc M và gõ phím Enter), bạn không thể quay ngược lại để điều chỉnh mà phải bắt đầu lại từ đầu. Phương tiện "make config" này chỉ tiện lợi cho những ai rất kinh nghiệm và nắm rõ mình cần gì trong cấu hình biên dịch nhân, nó cũng tiện lợi cho quy trình chỉnh cấu hình biên dịch nhân từ xa (xuyên qua console và không dùng được X11 forward vì lý do gì đó). Sau khi hoàn tất các câu hỏi, công cụ này sẽ lưu trữ một cấu hình biên dịch nhân (được lưu ở dạng .config trong thư mục chứa mã nguồn của Linux) và sẵn sàng cho bước tạo dependency cho kernel build. Nếu hồ sơ .config đã tồn tại từ lần biên dịch trước, nó sẽ bị viết chồng lên ở giai đoạn này.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;&amp;lt;insert hình&amp;gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make menuconfig&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; nâng cấp lên một mức cao hơn so với &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make config&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;. Công cụ này cần thư viện và binaries "ncurses" để tạo GUI đơn giản. Với công cụ này, bạn có thể tái điều chỉnh các chi tiết tuỳ thích mà không phải bắt đầu lại từ đầu (nếu lỡ chọn sai) như dùng &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make config&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;. Trên GUI đơn giản này, bạn có thể di chuyển, thay đổi các chọn lựa bằng cách dời chuyển phím mũi tên (lên xuống), chọn Y bằng phím Y, chọn N bằng phím N và chọn M bằng phím M. Với công cụ này, bạn cũng có thể tải một cấu hình biên dịch nhân có sẵn (đã làm từ trước và đã biên dịch thành công chẳng hạn) mà chẳng phải đi xuyên qua mọi chọn lựa để hình thành một cấu hình biên dịch nhân mới. Một đặc tính của công cụ này là nó chứa "help context sensitive" (phần giúp đỡ hoặc thông tin cho từng mục trong quá trình điều chỉnh configuration). Nếu bạn không nắm rõ giá trị hoặc tác dụng của module nào đó, bộ phận "help" này chắc chắn sẽ hữu ích. Sau khi đã hoàn thành các chọn lựa, bạn có thể lưu trữ một bản configuration trên máy để lần sau dùng lại và "exit" đồ nghề này. Ở giai đoạn này, một bản configuration được lưu lại (ở dạng .config trong thư mục chứa mã nguồn của Linux) và sẵn sàng cho bước tạo dependency cho kernel build. Tương tự như "make config", nếu hồ sơ .config đã tồn tại từ lần biên dịch trước, nó sẽ bị viết chồng lên.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;&amp;lt;insert hình&amp;gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make xconfig&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; có lẽ là phương tiện được dùng rộng rãi nhất, nhất là cho những hệ thống chạy X Window. &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make xconfig&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; cần trọn bộ thư viện Qt và X Window để tạo GUI. Các chọn lựa và cách di chuyển trong GUI này để điều chỉnh hoàn toàn giống như trường hợp dùng menuconfig và thêm một khả năng nữa là có thể dùng mouse để chọn. Nếu bạn cần tái biên dịch kernel và có thể dùng X Window thì nên dùng công cụ xconfig này vì nó dễ dùng nhất.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Trên Linux kernel 2.6.x series có thêm &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make gconfig&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;. Tương tự như &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make xconfig&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;, "gconfig" cũng tạo GUI config tool nhưng GUI này dựa trên thư viện Gtk.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;7.2.2 Một số điểm cần chú ý trong giai đoạn hình thành cấu hình biên dịch nhân&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- Dùng cấu hình biên dịch nhân có sẵn và điều chỉnh cho thích hợp với nhu cầu của mình. Nếu bạn dùng bản phân phối của RedHat, cấu hình biên dịch nhân có trong thư mục /boot ở dạng config-&amp;lt;KERNEL_VERSION&amp;gt; (hồ sơ cấu hình này từ các kernel do RedHat cung cấp). Để dùng cấu hình biên dịch nhân này, bạn có thể dùng &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make menuconfig&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; hoặc &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make xconfig&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; để tải configuration này lên và điều chỉnh theo ý muốn. Thật ra không có bất cứ tài liệu nào có thể giải thích cặn kẽ từng chọn lựa cho mỗi cấu hình máy cả. Ở mức độ tái biên dịch một kernel, bạn cần hiểu cấu hình máy và những chọn lựa trong một configuration đến mức độ có thể quyết định chọn lựa những gì cho thích hợp. Bản phân phối Debian cũng lưu trữ các cấu hình biên dịch nhân trong thư mục /boot tương tự như bản phân phối RedHat. Các bản phân phối khác có một số tương đồng và dị biệt, bạn nên tham khảo thêm các hướng dẫn cụ thể cho bản phân phối mình đang dùng.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- Lưu trữ cấu hình biên dịch nhân cho lần biên dịch kế tiếp. Nếu vì lý do gì đó khiến giai đoạn biên dịch kernel bị hỏng, bạn cần xem xét đoạn báo lỗi sau cùng khi công cụ biên dịch (compiler) thoát ra với "tình trạng không thành công" (exit status is not 0). Thông thường compiler thoát ra nửa chừng vì cách chọn lựa cấu hình biên dịch nhân có những điểm không thích hợp và thoả mãn (liên hệ nhau). Những lỗi được báo trên console giúp bạn xác định trục trặc nằm trong khu vực nào của cấu hình biên dịch nhân. Bạn chỉ cần tải hồ sơ biên dịch đã được lưu trữ lần cuối cùng lên và vào thẳng khu vực bị sự cố để xem xét và điều chỉnh, thay vì phải thiết lập từ dầu để tránh va vào những lỗi khác. Mỗi khi điều chỉnh và thay đổi cấu hình biên dịch nhân, bạn lại tiếp tục lưu lại một bản và đặt tên cho nó một cách hợp lý (ví dụ kernel-2.4.26-1 cho configuration thứ nhất, kernel-2.4.26-2 cho configuration thứ nhì.....).&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- Nếu bạn dùng một "vanilla" kernel, mã nguồn kernel được tải về từ kernel.org hoặc mirror site của nó (bài viết này tập trung chủ yếu vào "vanilla" kernel), sau khi hoàn thành bước &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make config&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; hoặc &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make menuconfig&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; hoặc &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make xconfig&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;, cấu hình biên dịch nhân đã được bạn điều chỉnh và chọn lựa sẽ đưọc lưu trữ ở dạng dấu (hidden) ở ./.config (các hồ sơ và thư mục bắt đầu bằng dấu chấm . được xếp loại là hidden files, chỉ có ls -la mới thấy chúng). Lần kế tiếp, sau khi chạy một trong số lệnh trên và tiếp nhận các thay đổi thì cấu hình biên dịch nhân lại tự động viết chồng lên ./.config. Cho nên, bạn có thể lưu trữ hồ sơ ./.config thành một hồ sơ có tên khác trước khi điều chỉnh và chọn lựa lần kế tiếp.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- Ngoài &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make config&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;, &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make menuconfig&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;, &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make xconfig&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; hoặc &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make gconfig&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; (cho kernel 2.6.x series), bạn còn có thể dùng một lệnh khác cho cả kernel series 2.4.x và 2.6.x là: &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make oldconfig&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;. &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make oldconfig&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; là một trường hợp đặc biệt dùng để đọc và dùng các chọn lựa đã có sẵn trong ./.config mà không cho bạn cơ hội đi xuyên qua để điều chỉnh và chọn lựa. Trường hợp này rất tiện lợi nếu bạn đã điều chỉnh và chọn lựa thành công một cấu hình biên dịch nhân cho mình. &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Kernel 2.6.x series còn có bốn target cho bước này:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;make defconfig&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;: tạo một cấu hình biên dịch nhân mới với chế độ mặc định cho mọi chọn lựa&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;make allmodconfig&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;: tạo một cấu hình biên dịch nhân mới với chế độ chọn lựa các modules khi có thể được&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;make allyesconfig&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;: tạo một cấu hình biên dịch nhân mới với chế độ tiếp nhận yes (Y) cho mọi chọn lựa&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;make allnoconfig&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;: tạo một cấu hình biên dịch nhân mới với chế độ tiêp nhận no (N) cho mọi chọn lựa. Chế độ này sẽ tạo ra một kernel rất nhỏ và đơn giản.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Hiếm khi bạn điều chỉnh một cấu hình biên dịch nhân Linux lần đầu mà không hề bị lỗi trong khi biên dịch. Cách lưu trữ từng configuration cho mỗi lần hiệu chỉnh là cách tốt nhất để bảo đảm "lỗi" lần trước sẽ không tái diễn. Nếu bạn chỉ đơn giản dùng cấu hình biên dịch nhân có sẵn (như RedHat Linux chứa trong /boot) và không điều chỉnh gì cả thì ngoài mục đích vá lỗi, lối dùng này chẳng có tác dụng gì về mặt nâng cao hiệu năng của máy.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;8. Các bước xây dựng&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;8.1 Bước tạo dependency, dọn dẹp và tạo kernel image&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Bước này có thể chạy ba lệnh:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;make dep&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;make clean&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;make bzImage&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;hoặc gom chung lại thành một nhóm:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;make dep clean bzImage&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Nếu bạn chạy dep, clean và bzImage riêng biệt thì phải trông chừng khi nào lệnh thứ nhất hoàn tất để tiếp tục chạy lệnh thứ nhì và tiếp theo. Nếu bạn chạy ba lệnh một lượt thì lệnh thứ nhì tự dộng nối tiếp lệnh thứ nhất và lệnh thứ ba nối tiếp lệnh thứ nhì. Bạn không cần phải chờ đợi.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- bước "dep" là bước tạo dependencies và các includes cần thiết cho kernel. Bước này có thể mất nhiều phút, tùy vào CPU của từng máy. Đối với kernel series 2.6.x, bước này không cần thiết nữa.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- sau khi xong bước "dep", bước "clean" dùng để dọn dẹp tất cả những "objects" vụn vặt, không còn cần thiết vì dependencies đã hoàn tất ở trên.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- bước kế tiếp "bzImage" là bước tạo kernel image. Đây là bước hết sức quan trọng trong ba bước này. Nếu có sự cố gì xảy ra thì phải quay lại điều chỉnh cấu hình biên dịch nhân và đi xuyên qua các bước "make dep", "make clean" trở lại (cần phải chạy một số lệnh dọn dẹp trước khi make dep clean bzImage trở lại, vấn đề này sẽ được đề cập trong phần 10). Trên máy chạy Athlon Thunderbird 1.4Ghz, tôi mất chừng 10 phút để hoàn thành bước này. Trên một máy Pentium 233MMX cũ, tôi mất hơn 40 phút mới hoàn thành bước tạo kernel image.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Nếu ba bước trên hoàn toàn thành công, bạn có thể tìm thấy "kernel image" nằm trong thư mục ./arch/$ARCH/boot, trong đó $ARCH là dòng phần cứng của kernel bạn muốn biên dịch. Nếu máy bạn thuộc dạng i386, bạn sẽ tìm thấy kernel image trong &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;./arch/i386/boot&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;. Kernel image này đã được tạo ra nhưng chưa được cài và ở bước này, nó chỉ lưu trong thư mục trên cho các bước về sau.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Thật ra có thể tạo nhiều dạng "kernel image". Dạng kernel image được tạo từ "make bzImage" là dạng phổ biến nhất hiện nay vì nó nén kernel image tốt nhất và thích hợp với hầu hết các loại computer. Bạn cũng có thể dùng:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;make zImage&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;, &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make zDisk&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; hoặc &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make zLilo&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; để tạo kernel image nếu kernel dự kiến rất nhỏ và không cần kỹ thuật nén cao độ như "bz". Dùng các dạng này cũng thích hợp trong trường hợp máy của bạn quá cũ và có thể có sự cố với "bzImage". Chỉ cần nắm một cách khái quát như sau:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- Phần &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;bz&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; hoặc &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;z&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; đi trước các image ở trên chỉ định cho loại nén nào được dùng với kernel image. &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- Phần &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;Image&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; hoặc &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;Disk&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; hoặc &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;Lilo&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; chỉ định cho "loại" kernel image.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- Kernel image này được xả nén "on-the-fly" trong quá trình boot vào Linux sau này.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Xuyên qua ba bước ở trên, bạn sẽ thấy vô số thông điệp chạy trên console (ở kernel 2.6.x thông điệp chạy trên console ít hơn rất nhiều). Bất cứ lỗi nào (error) được báo trong bước này đều phải điều chỉnh cấu hình biên dịch nhân và trở lại bước "make dep". Cho đến giai đoạn này, lý do gây ra lỗi thường là:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- đồ nghề dùng để biên dịch không đúng phiên bản (xem phần 4.1 và 4.2 cho kernel series này bạn đang biên dịch)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- điều chỉnh sai hoặc thiếu một số chọn lựa nào đó trong cấu hình biên dịch nhân. Xem lỗi báo trước khi compiler thoát ra để xác định lỗi này thuộc phần nào trong cấu hình biên dịch nhân mà chỉnh lại cho thích hợp, nên dùng phương pháp tải và lưu trữ cấu hình biên dịch nhân đã đề cập trong phần 7.2.2 ở trên&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- cấu hình máy quá thấp (memory / diskspace) không đủ để thực hiện ba bước ở trên. Nếu gặp sự cố này, nên nâng cấp máy hoặc dùng một máy khác để build kernel cho máy này.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Linux kernel 2.6.x series đơn giản hoá chỉ với một target "make all". Target này bao gồm luôn phần "make modules" trong bước 8.2 kế tiếp.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;8.2 Bước tạo modules và cài modules&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Bước này có thể chạy hai lệnh:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;make modules&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;make modules_install&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;hoặc gom chung lại thành một dòng:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;make modules modules_install&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Điểm khác biệt giữa cách chạy hai lệnh riêng biệt hoặc chạy chung một dòng lệnh ở đây nằm ở chỗ: &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- bạn có thể chỉ muốn biên dịch modules cho kernel mà không muốn cài (install) trên máy ngay sau khi các modules được biên dịch xong, &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- hoặc bạn chỉ muốn biên dịch modules trên máy này rồi sẽ mang qua máy khác để cài. &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Thông thường "make modules modules_install" đi chung vì ít người build modules trên một máy rồi mang đi cài trên một máy khác. Nếu chạy hai lệnh này một lượt, bạn phải chạy ở chế độ "super user" không thì modules không install được vì chỉ có root (super user) mới có thể "install" các modules vừa được biên dịch. Nếu bạn tách rời hai lệnh trên thì các lệnh tách rời như sau:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;make modules&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; # chạy bằng user account bình thường&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;su&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; # chuyển sang chế độ "super user"&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;[enter password]&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;make modules_install&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; # cài modules vừa biên dịch xong.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Bước "make modules" là bước biên dịch và tạo ra các modules (mà bạn đã chọn ở dạng M trong quá trình chỉnh lý cấu hình biên dịch nhân). Các modules đã được biên dịch sẽ được lưu trữ trong các thư mục thích ứng với từng nhóm "drivers" trong cây mã nguồn (kernel source tree). Giai đoạn này là giai đoạn biên dịch lâu nhất trong trọn bộ quá trình compiler thực sự biên dịch mã nguồn của kernel. Trên một máy chạy Athlon Thunderbird 1.4Ghz, bước này mất chừng 25 phút. Trong khi đó cùng số lượng modules cần biên dịch chạy trên máy Pentium 233MMX mất chừng trên 4 giờ đồng hồ.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Bước "make modules_install" sẽ "cài" các modules vừa được biên dịch vào thư mục &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;/lib/modules/&amp;lt;kernel_version&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;. Nếu liệt kê thư mục này (ls), bạn sẽ thấy ít nhất một thư mục chứa modules cho kernel đang chạy trên máy hoặc nhiều thư mục cho nhiều phiên bản kernel trước đây (có từ quy trình cập nhật kernel bằng rpm hoặc quy trình nào đó tuỳ theo bản phân phối, hoặc từ quy trình biên dịch kernel tương tự như bài viết này). Khi boot Linux bằng một phiên bản kernel nào đó có trên máy, các modules thuộc kernel này (trong thư mục thích ứng với kernel version) sẽ được ứng tải.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Đối với kernel 2.4.x series, bạn có thể tham khảo chi tiết thông tin về modules, cách biên dịch modules tổng quát và cách xử dụng modules (thuộc user space) trong hồ sơ ./Documentation/modules.txt thuộc mã nguồn kernel bạn dự định biên dịch.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Đối với kernel 2.6.x series, bạn có thể tham khảo chi tiết thông tin về modules, cách biên dịch modules tổng quát và cách xử dụng modules (thuộc user space) trong ba hồ sơ &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;./Documentation/kbuild/modules.txt&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;, &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;./Documentation/networking/net-modules.txt&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; và &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;./Documentation/sound/oss/README.modules&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; thuộc mã nguồn kernel bạn dự định biên dịch. Riêng với kernel 2.6.x series, bước "make modules" có thể thực hiện từ "make all" và bước "make modules_install" chỉ thực hiện riêng (ở chế độ super user) để cài các modules đã được biên dịch.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;8.3 Tách rời mã nguồn và hồ sơ output trên kernel 2.6.x series&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Nếu bạn đang dùng kernel 2.4.x series thì không cần tham khảo thông tin của mục 8.3. Những thông tin trong mục này chỉ giới thiệu thêm một số tiện ích hữu dụng cho quy trình chuẩn bị và biên dịch kernel 2.6.x.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;8.3.1 "make help", một tiện ích mới trên kernel 2.6.x series&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Ngoài những điểm khác biệt trong các make target đã được đề cập ở phần 8.1 và 8.2, trên kernel 2.6.x series, bạn có thể xử dụng một tiện ích khá hay mà kernel 2.4.x không có đó là phần "help" trước khi "make" mã nguồn của Linux kernel. Tất nhiên bạn phải chạy lệnh này sau khi vào trong thư mục chứa mã nguồn Linux kernel:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ cd /usr/src/linux-2.6.6&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; (dùng kernel 2.6.6 trong trường hợp này)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ make help&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; sẽ cho thông tin trợ giúp như sau:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;code&gt;bash-2.05b$ make help&lt;br /&gt;Cleaning targets:&lt;br /&gt; clean           - remove most generated files but keep the config&lt;br /&gt; mrproper     - remove all generated files + config + various backup files&lt;br /&gt;&lt;br /&gt;Configuration targets:&lt;br /&gt; oldconfig       - Update current config utilising a line-oriented program&lt;br /&gt; menuconfig   - Update current config utilising a menu based program&lt;br /&gt; xconfig         - Update current config utilising a QT based front-end&lt;br /&gt; gconfig         - Update current config utilising a GTK based front-end&lt;br /&gt; defconfig       - New config with default answer to all options&lt;br /&gt; allmodconfig    - New config selecting modules when possible&lt;br /&gt; allyesconfig    - New config where all options are accepted with yes&lt;br /&gt; allnoconfig     - New minimal config&lt;br /&gt;&lt;br /&gt;Other generic targets:&lt;br /&gt; all                   - Build all targets marked with [*]&lt;br /&gt;* vmlinux          - Build the bare kernel&lt;br /&gt;* modules         - Build all modules&lt;br /&gt; modules_install - Install all modules&lt;br /&gt; dir/                 - Build all files in dir and below&lt;br /&gt; dir/file.[ois]     - Build specified target only&lt;br /&gt; rpm                - Build a kernel as an RPM package&lt;br /&gt; tags/TAGS       - Generate tags file for editors&lt;br /&gt; cscope            - Generate cscope index&lt;br /&gt;&lt;br /&gt;Documentation targets:&lt;br /&gt; Linux kernel internal documentation in different formats:&lt;br /&gt; sgmldocs (SGML), psdocs (Postscript), pdfdocs (PDF)&lt;br /&gt; htmldocs (HTML), mandocs (man pages, use installmandocs to install)&lt;br /&gt;&lt;br /&gt;Architecture specific targets (i386):&lt;br /&gt;* bzImage       - Compressed kernel image (arch/i386/boot/bzImage)&lt;br /&gt; install       - Install kernel using&lt;br /&gt;                  (your) ~/bin/installkernel or&lt;br /&gt;                  (distribution) /sbin/installkernel or&lt;br /&gt;                  install to $(INSTALL_PATH) and run lilo&lt;br /&gt; bzdisk       - Create a boot floppy in /dev/fd0&lt;br /&gt; fdimage      - Create a boot floppy image&lt;br /&gt;&lt;br /&gt; make V=0|1 [targets] 0 =&amp;gt; quiet build (default), 1 =&amp;gt; verbose build&lt;br /&gt; make O=dir [targets] Locate all output files in "dir", including .config&lt;br /&gt; make C=1   [targets] Check all c source with checker tool&lt;br /&gt;&lt;br /&gt;Execute "make" or "make all" to build all targets marked with [*]&lt;br /&gt;For further info see the ./README file&lt;br /&gt;bash-2.05b$&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Thông tin trên cho thấy "Makefile" chính của kernel 2.6.x series bao gồm các mục tiêu (target) biên dịch khi chạy &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;make help&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;. Với thông tin này, bạn có thể chọn các target make theo ý muốn mà không phải kiểm tra trong "Makefile" như với kernel 2.4.x series (kernel 2.4.x series không có "make help" như kernel 2.6.x series và kernel 2.4.x series không có nhiều make targets như kernel 2.6.x series). Điểm đặt biệt cần quan tâm là ba chọn lựa cuối trong thông tin "make help" cung cấp:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;make V=0|1 [targets] 0 =&amp;gt; quiet build (default), 1 =&amp;gt; verbose build&lt;br /&gt; make O=dir [targets] Locate all output files in "dir", including .config&lt;br /&gt; make C=1   [targets] Check all c source with checker tool&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Một trong những chọn lựa quan trọng ở đây là nó cho phép bạn lưu trữ trọn bộ các hồ sơ output trong quá trình biên dịch vào một thư mục riêng biệt thay vì chứa chung với mã nguồn của kernel.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;8.3.2 Tách rời mã nguồn và output files&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Kernel 2.6.x series cho phép bạn tách rời mã nguồn của kernel và các hồ sơ output được tạo trong quá trình compile, các hồ sơ dấu (hidden) như .config, .depend.... trong các bước đề cập ở phần 7 và 8 cũng sẽ được lưu trữ ở thư mục nào bạn muốn dùng cho output files. Với phương tiện này, mã nguồn và các hồ sơ output sẽ không xen kẽ chung. Điểm quan trọng cần nhớ là khi đã dùng chọn lựa này thì &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;phải&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; dùng cho các bước "make" khác trong suốt quá trình biên dịch. Ví dụ, bạn có thể khởi đầu bằng:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;make O=/path/to/output xconfig&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;thì các bước kế tiếp sẽ là:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;make O=/path/to/output all&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; (target "all" bao gồm "dep, clean, bzImage, modules"), và&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;make O=/path/to/output modules_install&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; (chạy lệnh này bằng super user để cài modules của kernel).&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;&amp;lt;còn tiếp&amp;gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37459183-7706525399598352158?l=conmale.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://conmale.blogspot.com/feeds/7706525399598352158/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37459183&amp;postID=7706525399598352158' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/7706525399598352158'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/7706525399598352158'/><link rel='alternate' type='text/html' href='http://conmale.blogspot.com/2007/06/bin-dch-linux-kernel-phn-3.html' title='Biên dịch Linux kernel - phần 3'/><author><name>conmale</name><uri>http://www.blogger.com/profile/16598933828282382048</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/-2pIWb2iUysc/TzSYz5aVJYI/AAAAAAAAAAQ/BCWx8yVHmbU/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37459183.post-2885085344400203829</id><published>2007-06-19T20:50:00.000+10:00</published><updated>2007-06-20T19:59:49.522+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Biên dịch Linux kernel - phần 2</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;6.3 Kiểm tra thực tính của mã nguồn&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Điều quan trọng khi tải mã nguồn của kernel, nên tải gpg .sign cho phiên bản tương ứng. Mục đích là để kiểm tra thực tính của mã nguồn được tải về. Khi mã nguồn của Linux kernel được công bố, chúng được dồn lại thành một gói .tar và sau đó được nén bằng GNUzip hoặc bzip2, cả hai loại này sau khi được nén đều được tạo "chữ ký" .sign. &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Kiểm tra thực tính của mã nguồn được tải về bằng phương pháp kiểm tra "chữ ký" của từng gói mã nguồn là một thói quen cần thiết. Lý do: các mã nguồn mở nói chung được công bố và phổ biến rộng rãi, ai cũng có thể chỉnh sửa (một cách không chính thức và không được nhóm phát triển chính thức cho phép) rồi đưa lên một server nào đó trên Internet. Người dùng tải về, biên dịch và cài trên máy mà không kiểm tra thực tính của chúng (và mã nguồn này có những thay đổi mờ ám) thì hậu quả khó mà lường. &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Quy trình kiểm tra "chữ ký" chỉ đơn giản gói gọn trong một dòng lệnh:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ gpg --verify linux-2.4.26.tar.bz2.sign linux-2.4.26.tar.bz2&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;, trong đó&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;linux-2.4.26.tar.bz2.sign&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; là "chữ ký" của gói linux-2.4.26.tar.bz2 được tải về từ server chứa mã nguồn Linux kernel&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;linux-2.4.26.tar.bz2&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; là gói mã nguồn Linux kernel được nén bằng bzip2&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Trước khi có thể kiểm tra thành công bằng lệnh trên, bạn phải có &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;gpg&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; đã cài trong máy, tải và nhập public key của server chứa mã nguồn Linux kernel mà bạn tải về. Chi tiết hướng dẫn cho quy trình này ở:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;a style="font-family: verdana;" target="_BLANK" href="http://www.kernel.org/signature.html"&gt;http://www.kernel.org/signature.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Quy trình tải mã nguồn Linux kernel và kiểm tra thực tính của mã nguồn này có thể tóm tắt bằng một ví dụ như sau:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;# chuyển vào thư mục chứa mã nguồn của máy ở /usr/src là nơi thông thường. Đối với kernel 2.6.x series, bạn có thể dùng thư mục khác tùy ý:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;cd /usr/src&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;# dùng wget để lấy một phiên bản mã nguồn từ server về ở dạng .bz2&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;wget &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;a style="font-family: verdana;" target="_BLANK" href="http://www.kernel.org/pub/linux/kernel/v2.4/linux-2.4.26.tar.bz2"&gt;http://www.kernel.org/p...2.4/linux-2.4.26.tar.bz2&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;# dùng wget để lấy .sign của phiên bản mã nguồn vừa được tải về&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;wget &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;a style="font-family: verdana;" target="_BLANK" href="http://www.kernel.org/pub/linux/kernel/v2.4/linux-2.4.26.tar.bz2.sign"&gt;http://www.kernel.org/p...inux-2.4.26.tar.bz2.sign&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;# Dùng gpg với option verify để kiểm thực tính của mã nguồn vừa tải về&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;gpg --verify linux-2.4.26.tar.bz2.sign linux-2.4.26.tar.bz2&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Ngoài phương pháp dùng signature cho vấn đề kiểm chứng thực tính của mã nguồn (không chỉ mã nguồn của Linux kernel) , bạn cũng thấy rất nhiều nơi trên Internet dùng "MD5sum" cho mục đích này (cho đến nay, mã nguồn Linux kernel dùng signature để kiểm chứng, không dùng MD5sum). Quy trình kiểm tra "MD5sum" chỉ đơn giản là một quy trình tạo một "MD5sum" từ mã nguồn được tải về trên máy và so sánh kết quả "MD5sum" này với hồ sơ "MD5sum" được tải về kèm với mã nguồn. Nếu "MD5sum" bạn tạo ra trên máy của mình với cùng gói mã nguồn mà không trùng hợp với "MD5sum" nguyên thuỷ tải về từ server thì thực tính của phần mã nguồn này không đáng tin cậy. Cách tốt nhất là chỉ nên tải mã nguồn ở những địa chỉ phố biến và đáng tin cậy. Cẩn thận hơn nữa (really paranoid), thì so sánh MD5sum với một số server chứa mã nguồn khác nhau.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- Kiểm tra thực tính của mã nguồn bằng MD5 checksum khá đơn giản. Tiện ích &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;md5sum&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; có sẵn hần như trên mọi bản phân phối. Lệnh tạo MD5 checksum đơn giản là lệnh:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;# md5sum &amp;lt;file_cần_kiểm_tra&amp;gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;sẽ tạo ra 1 chuỗi chữ và số tương tự như: &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;2fe2a5fabcc3a33722b4ffe05714bec3 *&amp;lt;file_cần_kiểm_tra&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;. Nếu chuỗi này trùng với chuỗi được cung cấp chính thức với mã nguồn thì mã nguồn này có thực tính và đáng tin cậy.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;6.4 Xả nén mã nguồn&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Tùy vào gói mã nguồn được tải về thuộc dạng nén .gz hay .bz2 mà dùng tiện ích thích hợp để xả nén. Như đã tóm tắt trong phần 6.3 ở trên, gói mã nguồn được chứa trong /usr/src (wget được chạy sau khi cd vào /usr/src), cho nên bạn phải ở trong thư mục này trước khi thao tác các bước kế tiếp (không thì các bước kế tiếp phải thêm và đường dẫn đến nơi chứa gói mã nguồn). Đối với kernel 2.6.x series, mã nguồn của Linux kernel có thể được xả, chứa và biên dịch từ bất cứ nơi đâu mà bạn có quyền chứa trên hệ thống. Tuy nhiên, để giữ cho hệ thống sạch và thống nhất, bạn nên giữ mã nguồn ở /usr/src.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- nếu gói mã nguồn có dạng .gz thì dùng: &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ gunzip linux-2.x.xx.tar.gz&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; (x.xx là bất cứ phiên bản nào bạn tải về).&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ tar xf linux-2.x.xx.tar&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; (lệnh này dùng option &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;x&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; để extract (xả) và &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;f&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; để chỉ định hồ sơ nào cần được xả, ở đây hồ sơ cần được xả là linux-2.x.22.tar).&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Hai lệnh trên cũng có thể gọp chung lại như sau:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ tar xfz linux-2.x.xx.tar.gz&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; (lệnh này dùng thêm option &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;z&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; để ngầm xả nén .gz file "on-the-fly" trước khi xả gói tar).&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Hoặc có thể tạo cùng kết quả bằng cách khác nữa:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ gzip -dc linux-2.x.xx.tar.gz | tar xvf -&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; (cụm lệnh này dùng chương trình gzip để xả nén (option -d) ra stdout (option -c) và "tee" nó qua chương trình tar để xả gói tar ra "on-the-fly". Cả cách này và cách ở trên đều tiện dụng cho những ai eo hẹp dung lượng trên đĩa).&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;- nếu gói mã nguồn có dạng .bz2 thì dùng:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ bunzip2 linux-2.x.xx.tar.bz2&lt;/b&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ tar xf linux-2.x.xx.tar&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Hai lệnh trên cũng có thể gọp chung lại như sau:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ tar xfj linux-2.x.xx.tar.bz2&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; (lệnh này dùng thêm option &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;j&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; để ngầm xả nén .bz2 file "on-the-fly" trước khi xả gói tar).&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Hoặc có thể tạo cùng kết quả bằng cách khác nữa:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;$ bzip2 -dc linux-2.x.xx.tar.bz2 | tar xvf -&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; (cụm lệnh này dùng chương trình bzip2 để xả nén (option -d) ra stdout (option -c) và "tee" nó qua chương trình tar để xả gói tar ra "on-the-fly". Cả cách này và cách ở trên đều tiện dụng cho những ai eo hẹp dung lượng trên đĩa).&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Cả ba trường hợp đều cho kết quả là một thư mục có tên là linux-2.x.xx bên trong thư mục /usr/src/&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Trong phần này, chúng ta chỉ đề cập đến trường hợp tải trọn bộ mã nguồn của Linux kernel về để biên dịch. Trường hợp đã có mã nguồn cũ hơn của Linux kernel trên máy và chỉ cần tải patch và "vá" thì có quy trình khác. Vấn đề này sẽ đề cập sau.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;6.5 Dùng "config" nào thì thích hợp?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Cấu hình biên dịch nhân Linux đơn giản là một "text file" chứa các biến với giá trị Y (Yes), N (No) hoặc M (Module). Các giá trị này được xử dụng trong quá trình biên dịch; chúng dùng để xác định những gì không được biên dịch, những gì được biên dịch và nếu được biên dịch thì sẽ theo dạng nào.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Tùy vào cách sắp xếp của mỗi Linux bản phân phối, cấu hình biên dịch nhân Linux nằm nhiều nơi khác nhau. Hồ sơ cấu hình theo mặc định của "vanilla" kernel nằm ở &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;./arch/i386/defconfig&lt;/b&gt; (nếu dùng dòng phần cứng IA32 nói chung), các hồ sơ cấu hình khác cho những dòng phần cứng khác nằm ở &lt;b style="font-family: verdana;"&gt;./arch/$ARCH/defconfig&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;; trong đó $ARCH là dòng phần cứng của máy. Nếu dùng cấu hình mặc định, không chỉnh sửa thì kernel sẽ được tái biên dịch trọn bộ theo giá trị mặc định và chắc hẳn, kernel này sẽ không thích hợp cho bạn (ngay cả nếu nó được biên dịch thành công). Điều này đi ngược lại mục đích cần tái biên dịch Linux kernel ngay từ đầu. Bạn có thể dùng hồ sơ cấu hình này để khởi đầu và chỉnh sửa giá trị cho thích hợp. Đây là một bước rất khó khăn cho những ai chưa từng đi qua giai đoạn này và không có sẵn một cấu hình biên dịch nhân hoàn chỉnh cho máy.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Cấu hình cho kernel hiện hữu trên máy cũng có thể nằm trong thư mục /boot ở dạng config-2.x.xx nếu bạn dùng kernel do RedHat (hoặc dựa RedHat) và một số bản phân phối khác cung cấp. Bạn có thể an toàn dùng cấu hình này và chỉnh sửa, loại bỏ các chi tiết (driver module) không cần dùng. Nếu hệ thống đã được biên dịch kernel trước đây, bạn có thể tìm thấy cấu hình biên dịch nhân Linux có tên là .config, được lưu trong thư mục &amp;lt;KERNEL_SRC&amp;gt; (nơi trước đây mã nguồn của kernel được xả nén và biên dịch).&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;7. Chỉnh cấu hình biên dịch nhân Linux &lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;7.1 Thành phần của cấu hình biên dịch nhân Linux &lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Thành phần trong cấu hình biên dịch nhân Linux cho kernel 2.4.x và 2.6.x có một số tương đồng và dị biệt. Tuy nhiên, quy trình chọn Y, N hoặc M cho các modules vẫn như nhau. Bước chọn lựa và chỉnh liệu cấu hình biên dịch nhân Linux là một bước mất nhiều thời gian nhất, nó cũng là một bước gây nhiều trở ngại nhất nếu chỉnh sửa không hợp lý hoặc thiếu sót.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;7.1.1 Thành phần cấu hình biên dịch nhân Linux thuộc kernel 2.4.x series&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Code Maturity Level Options&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Chọn lựa của mục này cho phép dùng các modules / drivers còn ở trạng thái "alpha" (thử nghiệm). Nếu hệ thống làm việc là một máy production, cần tính ổn định cao thì nên tắt bỏ chọn lựa của phần này. Làm như thế sẽ tắt bỏ &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;rất nhiều&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; modules / drivers thuộc dạng "alpha" trong những phần bên dưới. Nếu muốn thử dùng một số modules / drivers ở dạng alpha thì nên cho phép phần này (Y) và cẩn thận khi lựa chọn các modules được biên dịch sau này. Việc chọn lựa các "alpha" drivers ở chế độ mặc định của các kernel trong nhiều bản phân bố Linux là một trong những nguyên nhân chính tạo nên tình trạng bất ổn định trên một số hệ thống Linux. Nếu chọn lựa các driver này một cách cẩn thận, cơ hội va phải tình trạng bất ổn định sẽ giảm thiểu rõ rệt.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Loadable Module Support&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Đây là chức năng nòng cốt của Linux kernel (loadable module). Như đã đề cập ở phần tổng quan (phần 1), loadable modules tiện dụng và linh động, cho nên bạn gần như sẽ chọn Y trong trường hợp này. Trong trường hợp bạn cần dùng kernel modules được viết thêm bên ngoài kernel tree chính thức (3rd party modules), bạn phải chọn "enable set version information on all modules symbols" trong mục này. Nếu bạn cần biên dịch trọn bộ các drivers thẳng vào kernel và không dùng modules (vì lý do bảo mật chẳng hạn), bạn có thể chọn N ở đây. Bạn cũng phải chọn "Y" cho trọn bộ các drivers trong cấu hình biên dịch nhân để thích hợp với chọn lựa "N" cho phần Loadable Module Support này.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Processor Type and Features&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Phần này có lẽ là phần tối quan trọng trong cấu hình biên dịch nhân Linux. Đây là nơi để chọn đúng CPU đang dùng trên máy. Ngoài ra còn rất nhiều chọn lựa khác nhau cho vấn đền system scheduling, SMP (symetrical multi-processing) nếu máy có nhiều CPU, hỗ trợ số lượng lớn memory có trong máy.... Nếu bạn chon CPU là i386 thì có lẽ sẽ không có sự cố vì i386 là architecture chung nhất (cả Intel và AMD CPU đều chạy với chọn lựa i386). Tuy nhiên, chọn lựa này sẽ không đạt hiệu năng tối đa và thích hợp cho từng loại CPU cụ thể. Nên chọn đúng CPU để bảo đảm hiệu năng của máy và nhất là để tránh trường hợp không thể boot vào Linux sau khi cài kernel mới (vì loại CPU chỉnh định cho kernel không đúng với CPU có trên máy hay nói một cách kỹ thuật, instructions giữa kernel và máy không tương đồng).&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;General Setup&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Mục này cho phép chọn lựa các ứng dụng hỗ trợ cho những thiết bị (cards) trên máy như ISA, PCI, PCMCIA và các chức năng thuộc về vấn đề quản trị năng lượng nâng cấp (Advanced Power Management). &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Memory Technology Devices&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Phần này cho phép lựa chọn những ứng dụng thiết bị liên hệ đến memory. Nếu bạn dùng các thiết bị như digital camera hoặc các loại compact flash thì bạn nên chỉnh lý phần này cho thích hợp. &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Block Devices&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Đây là một phần rất quan trọng trong cấu hình biên dịch nhân Linux. Nó bao gồm các chọn lựa cho những thiết bị thông thường và cần thiết như đĩa cứng, đĩa mềm, băng lưu trữ cũng như các thiết bị điều tác (controllers) cho parallel ports và RAID. Hầu như các chọn lựa trong mục này đều cần thiết; đặc biệt là chức năng hỗ trợ initrd cần thiết để tải sẵn các drivers cần thiết ở dạng module trong quá trình boot máy. &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Multi-Device support (RAID and LVM)&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Phần này chuyên chú đến các chức năng cần thiết cho hệ thống ở cấp độ server. Các chọn lựa ở đây hỗ trợ những thiết bị như RAID và LVM. Nếu máy của bạn hiện đang dùng RAID và LVM thì không thể bỏ qua phần này trong quá trình xác lập cấu hình biên dịch nhân Linux. Chọn lựa trong phần này đòi hỏi phải hiểu rõ nhu cầu dùng những công nghệ thuộc dạng này trên máy. Nếu máy không dùng đến những công nghệ này, bạn có thể an toàn tắt bỏ chúng (dùng N). Nên nhớ, nếu tắt bỏ RAID trong phần này thì phải tắt bỏ chọn lựa RAID trong phần "block devices" ở trên để tránh gặp phải lỗi biên dịch sau này.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;ATA/IDE/MFM/RLL support&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Phần này bao gồm các chọn lựa và hỗ trợ cho IDE và ATAPI dùng trên các pc-compatible (và trên nhiều architecture khác hiện có trên thị trường). Hầu hết các hệ thống cần các chức năng hỗ trợ trong phần này.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Cryptography Support (CryptoAPI)&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Đây là một phần khá mới và lý thú  trong mã nguồn của Linux kernel 2.4.x (chỉ được giới thiệu và công bố trong các phiên bản sau này của 2.4.x). Phần này có những lựa chọn thuộc về vấn đề "mã hoá" cho filesystems. Bạn có thể biên dịch các chọn lựa trong mục này và xử dụng (hoặc không) trên máy tùy ý.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Networking Options&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Đây là một phần cực kỳ quan trọng trong cấu hình biên dịch nhân Linux nếu bạn muốn máy của mình gắn liền với mạng. Nó bao gồm các chọn lựa cho cả IPv4 và IPv6 networking. Đây cũng là một phần hết sức phức tạp, cho nên, để có thể hiểu rõ và chọn lựa đúng cho hiệu năng tối đa của máy về mặt networking, bạn nên tham khảo rộng rãi các tài liệu về Linux networking, ít nhất là nên đọc các tài liệu kèm theo trong mã nguồn Linux kernel ở &amp;lt;KERNL_SRC&amp;gt;/Documentation/networking/ (thường là /usr/src/linux-2.x.xx/Documentation/networking/). &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;SCSI Support&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Phần chọn lựa cho SCSI ít được những người dùng PC bình thường quan tâm đến vì không mấy ai dùng SCSI cho máy con. Tuy nhiên nếu bạn dùng SCSI card (hoặc SCSI built-in trên motherboard) hoặc dùng CDR/W qua IDE nhưng chạy ở dạng SCSI emulation thì phải điều chỉnh các chọn lựa trong mục này. Điều quan trọng cần nhớ, nếu không dùng tiện dụng initrd, khi chọn lựa SCSI cho một filesystem chạy trên SCSI disk bạn &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;phải&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; biên dịch trực tiếp các chọn lựa cho SCSI vào kernel thay vì dùng dưới dạng module. Nếu không, kernel sẽ treo trong giai đoạn Linux kernel boot vì module hỗ trợ SCSI chưa được load trong giai đoạn này. &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Character Devices&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Trong mục này có khá nhiều lựa chọn tập trung vào các thiết bị như serial và parellel, mouse, joysticks (để chơi games). Tắt hoặc mở các lựa chọn trong mục này thường ít tạo ảnh hưởng nghiêm trọng.  &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;File Systems&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Mục này chứa trọn bộ các chọn lựa liên quan đến file system và các loại file system được hỗ trợ trên Linux (bao gồm các file system thường được hỏi đến như FAT, FAT32, NTFS, ISO cho CD-ROM....). Các file system phụ trợ như NTFS, FAT... có thể được biên dịch như một module cho kernel. &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;Không nên&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; biên dịch các modules cho file system dùng để "mount" trong giai đoạn boot như ext3, jbd &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;u style="font-family: verdana;"&gt;mà nên biên dịch thẳng vào kernel&lt;/u&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; (Lý do tương tự như đã đề cập trong phần "SCSI Support" ở trên). Cách này sẽ làm kích thước kernel lớn hơn nhưng sẽ an toàn và đơn giản hơn. Chức năng hỗ trợ initrd có thể dùng để tải các modules cần thiết trong quá trình Linux kernel boot nhưng phải nhớ bật chức năng này lên trong phần &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;block devices&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;. Đây là vấn đề tùy chọn của từng cá nhân.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;7.1.2 Thành phần Linux kernel configuration thuộc kernel 2.6.x series&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Code Maturity Level Options&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Phần này tương tự như đã đề cập ở trên cho kernel 2.4.x series &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;General Setup&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Phần này tương tự như đã đề cập ở trên cho kernel 2.4.x series&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Loadable Module Support&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Phần này tương tự như đã đề cập ở trên cho kernel 2.4.x series &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Processor Type and Features&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Phần này tương tự như đã đề cập ở trên cho kernel 2.4.x series&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Power Management Options&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt; &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Phần này tương tự như đã đề cập ở trên cho kernel 2.4.x series &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Executable File Formats&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Đây là một mục riêng biệt trong cấu hình biên dịch nhân của series 2.6.x. Nếu bạn quan tâm đến "a.out", "elf" và "misc", nên nghiên cứu kỹ phần này qua các tài liệu kèm theo với mã nguồn kernel, đặt biệt cho các tiện dụng của "misc" (&amp;lt;KERNEL_SRC&amp;gt;/Documentation/mono.txt, &amp;lt;KERNEL_SRC&amp;gt;/Documentation/binfmt_misc.txt, &amp;lt;KERNEL_SRC&amp;gt;/Documentation/filesystem/proc.txt)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Device Drivers&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Đây là một mục mới trong phần cấu hình biên dịch nhân của series 2.6.x. Thật ra device drivers nằm rải rác khắp nơi trong kernel build configuration của series 2.4.x. Ở series 2.6.x, mọi vấn đề liên quan đến "device drivers" được gom lại trong cùng một nhóm. Các chọn lựa thuộc về các thiết bị như graphic card, sound card, USB, SCSI và vấn đề hiệu chỉnh chúng đều tập trung ở đây.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;File Systems &lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Phần này tương tự như đã đề cập ở trên cho kernel 2.4.x series&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;Security Options&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;Phần này dành riêng cho các vấn đề về bảo mật của kernel. Cho đến nay vẫn còn đang phát triển, tuy nhiên, đây là phần đầy hứa hẹn cho một Linux kernel mang tính bảo mật cao.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;&amp;lt;còn tiếp&amp;gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37459183-2885085344400203829?l=conmale.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://conmale.blogspot.com/feeds/2885085344400203829/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37459183&amp;postID=2885085344400203829' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/2885085344400203829'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/2885085344400203829'/><link rel='alternate' type='text/html' href='http://conmale.blogspot.com/2007/06/bin-dch-linux-kernel-phn-2.html' title='Biên dịch Linux kernel - phần 2'/><author><name>conmale</name><uri>http://www.blogger.com/profile/16598933828282382048</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/-2pIWb2iUysc/TzSYz5aVJYI/AAAAAAAAAAQ/BCWx8yVHmbU/s220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37459183.post-6748638033645900735</id><published>2007-05-16T15:04:00.000+10:00</published><updated>2007-06-20T19:58:33.659+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Biên dịch Linux kernel - phần 1</title><content type='html'>&lt;p  style="font-family:verdana;"&gt;&lt;span style="font-size:85%;"&gt;&lt;strong&gt;Biên dịch Linux kernel - phần 1&lt;/strong&gt;&lt;br /&gt;Hướng dẫn chi tiết các bước trong quá trình tái biên dịch Linux kernel cho kernel 2.4.x và 2.6.x.&lt;br /&gt;Tổng lược về Linux kernel và những yếu tố cần chuẩn bị.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style=";font-family:verdana;font-size:85%;"  &gt;Compile Linux Kernel&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;1. Tổng quan về Linux kernel trên phương diện tái biên dịch&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;1.1 Linux kernel và vấn đề tái biên dịch:&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:verdana;font-size:85%;"  &gt;Linux kernel là một "modern kernel", nặng tính modular. Từ kernel phiên bản 2.6.x trở đi, có rất nhiều chức năng và mở rộng được đưa vào kernel. Với tinh thần "compile kernel", một yếu tố chính yếu và quan trọng nhất cần ghi nhận đó là tính phân bộ (modularity) của Linux kernel.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:verdana;font-size:85%;"  &gt;Đối với người dùng bình thường, tính modularity này cho phép chọn lựa cách biên dịch các drivers kernel theo dạng modules hay theo dạng biên dịch trực tiếp vào kernel. Thông thường, kernel build configuration cho phép ba chọn lựa: Y, M và N cho mỗi "driver" trong kernel configuration. Có những "driver" không thể compile như một module vì nó phải được load and link trực tiếp ngay khi kernel khởi động. Cũng có những "driver" cho phép chọn như một module và được load trong khi và sau khi kernel được boot. Điểm chính yếu cần nắm bắt trong giới hạn chủ đề "compile Linux kernel" là hiểu rõ tại sao phải chọn M (cho module), Y (cho compile trực tiếp) và N (không dùng) các drivers này.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:verdana;font-size:85%;"  &gt;- Biên dịch trực tiếp vào kernel có nghĩa là các "drivers" này dù có được dùng hay không vẫn được load lên khi kernel khởi tác và tất nhiên nó sẽ chiếm một phần memory. Lợi điểm chính của chọn lựa này là một khi "drivers" đã được compile vào kernel thì không còn phải quan ngại đến tính trung thực của kernel và các driver nữa. Các hệ thống làm việc đòi hỏi tính bảo mật cao không dùng modules mà compile thẳng vào kernel để tránh trường hợp các modules không tin cậy "bị" cài vào kernel lúc nào đó trong quá trình hoạt động của máy. Lợi điểm kế tiếp của chọn lựa này là tính hiệu xuất (rất nhỏ), khi cần driver thì đã có sẵn và không cần ứng tải nữa.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:verdana;font-size:85%;"  &gt;- Biên dịch như các modules cho kernel có nghĩa là chỉ khi nào cần dùng các "drivers" này mới được ứng tải. Lợi điểm của chọn lựa này nổi bật ở khía cạnh xử dụng memory và tài nguyên trên máy. Với lựa chọn này, bạn có thể tạo nên một kernel cực nhỏ và dễ dàng di chuyển cho nhiều mục đích khác nhau. Lợi điểm kế tiếp là khả năng tái biên dịch chỉ một hoặc một số modules nào đó (cần cập nhật chẳng hạn). Tất nhiên để thực hiện chuyện này thì phải thoả mãn tất cả những đòi hỏi về dependency cho system.&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="font-family: verdana;"&gt;1.2 Tóm tắt các bước biên dịch (dành cho những kẻ thiếu kiên nhẫn ;))&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:verdana;font-size:85%;"  &gt;Biên dịch Linux kernel rất đơn giản nếu như đã hiểu rõ các quy trình và các bước thực hiện. Sau đây là các lệnh cần thiết, giả định bạn &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;đã có trọn bộ&lt;/b&gt;&lt;/span&gt;&lt;span style=";font-family:verdana;font-size:85%;"  &gt; các công cụ để biên dịch và các công cụ này đúng phiên bản:&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:verdana;font-size:85%;"  &gt;1. &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;$ cd /usr/src&lt;/b&gt;&lt;/span&gt;&lt;span style=";font-family:verdana;font-size:85%;"  &gt; # chuyển vào thư mục /usr/src, nơi thông thường chứa mã nguồn để biên dịch kernel&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:verdana;font-size:85%;"  &gt;2. &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;b style="font-family: verdana;"&gt;$ wget &lt;a target="_blank" href="http://www.kernel.org/pub/linux/kernel/v2.x/%3CKERNEL_SRC%3E.tar.bz2"&gt;http://www.kernel.org/pub/linux/kern...&gt;.tar.bz2&lt;/a&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=";font-family:verdana;font-size:85%;"  &gt; (&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;kernel_src style="font-family: verdana;"&gt; là phiên bản kernel cần biên dịch, ví dụ ở đây tải mã nguồn được nén ở dạng bz2)&lt;br /&gt;&lt;br /&gt;3. &lt;b&gt;$ gpg --verify &lt;kernel_src&gt;.tar.bz2.sign &lt;kernel_src&gt;.tar.bz2&lt;/kernel_src&gt;&lt;/kernel_src&gt;&lt;/b&gt; (xác thực chữ ký và thực tính của mã nguồn)&lt;br /&gt;&lt;br /&gt;4. &lt;b&gt;$ bzip2 -dc &lt;kernel_src&gt;.tar.bz2 | tar xvf -&lt;/kernel_src&gt;&lt;/b&gt; (xả nén gói chứa mã nguồn)&lt;br /&gt;&lt;br /&gt;5. &lt;b&gt;$ make xconfig&lt;/b&gt; (dùng GUI để điều chỉnh các chọn lựa cho kernel build configuration và lưu trữ configuration)&lt;br /&gt;&lt;br /&gt;6. &lt;b&gt;$ make dep clean bzImage&lt;/b&gt; (tập họp lệnh để tạo dependencies và includes, tiếp theo là dọn dẹp các objects không cần thiết và kernel image ở dạng nén)&lt;br /&gt;&lt;br /&gt;7. &lt;b&gt;$ make modules&lt;/b&gt; (biên dịch các modules đã được chọn lựa)&lt;br /&gt;&lt;br /&gt;8. &lt;b&gt;$ su&lt;/b&gt; (chuyển sang chế độ super user cho lệnh tiếp theo)&lt;br /&gt;&lt;br /&gt;9. &lt;b&gt;# make modules_install&lt;/b&gt; (cài các modules vào /lib/modules/&lt;kernerl_src&gt;, chỉ có super user mới có thể thực hiện lệnh này)&lt;br /&gt;&lt;br /&gt;10. &lt;b&gt;# make install&lt;/b&gt; (cài kernel vào máy, bước này bao gồm quy trình cài các hồ sơ cần thiết vào thư mục /boot)&lt;br /&gt;&lt;br /&gt;Bước thứ 10 có thể thay thế bằng một loạt thao tác bằng tay (chi tiết ở phần 9.2) nếu như Linux distribution không có sẵn một số công cụ thuộc gói &lt;b&gt;mkinitrd&lt;/b&gt; chỉ có trong RedHat distribution và các distribution dựa trên RedHat.&lt;br /&gt;&lt;br /&gt;Lưu ý: đối với kernel 2.6.x series, bạn có thể dùng các bước như trên. Tuy nhiên bước "make dep" không cần thiết nữa. Bài viết này bao gồm kernel 2.4.x và 2.6.x series nên có một số chi tiết không cần thiết cho kernel 2.6.x. Tuy vậy, những chi tiết này sẽ không ảnh hưởng đến sự thành công của quy trình biên dịch kernel.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. Tại sao cần compile lại Linux kernel?&lt;/b&gt;&lt;br /&gt;Đối với người dùng đã quen với những hệ điều hành "đóng" thì khái niệm tái biên dịch kernel là một khái niệm hết sức lạ lẫm. Điều này cũng dễ hiểu vì kernel của các hệ điều hành "đóng" hiển nhiên là "đóng" và người dùng bình thường không thể có cơ hội tiếp cận với mã nguồn của kernel cho thao tác quy trình tái biên dịch. Trong khi đó, mã nguồn của Linux kernel hoàn toàn "mở" và đây là phương tiện cũng như động lực tiên quyết cho vấn đề tái biên dịch kernel. Câu hỏi được đặt ra là tại sao lại cần phải tái biên dịch Linux kernel?&lt;br /&gt;&lt;br /&gt;Câu trả lời ngắn: không cần nếu như không cần và cần nếu như cần :)&lt;br /&gt;&lt;br /&gt;Câu trả lời dài: có vô số lý do khiến cho người dùng cần phải tái biên dịch Linux kernel. Sau đây là một số trường hợp thường gặp nhất:&lt;br /&gt;a. tái biên dịch kernel để chữa lỗi của kernel. Nếu các lỗi này thuộc về lõi của kernel thì phải vá nguồn của kernel và tái biên dịch nó để sửa chữa các lỗi được công bố.&lt;br /&gt;&lt;br /&gt;b. tái biên dịch kernel để nâng cao hiệu năng của kernel. Theo mặc định, các Linux distribution thường kèm một phiên bản kernel biên dịch với hầu hết những thành phần có sẵn để có thể đáp ứng rộng rãi cấu hình hardware (có thể hiện diện trên các máy). Đây là điểm lợi tổng quát lúc khởi điểm. Tuy nhiên, sau khi đã cài thành công và nắm chắc máy có những thiết bị gì (sound card, graphic card, network cards, SCSI card..... ) và biết rõ cần những thành phần nào cho cấu hình của máy thì không có lý do gì phải bao gồm trọn bộ các thứ không cần thiết và không dùng. Đối với kernel 2.4.x, mức độ nâng cao hiệu năng không rõ rệt (ngoại trừ dùng phương pháp test load để đo). Tuy nhiên, từ kernel 2.6.x trở đi, tính hiệu năng qua việc tái biên dịch và điều chỉnh "driver" modules cho kernel tạo hiệu xuất rõ rệt, nhất là trong việc điều chỉnh "thời biểu" (scheduling) của các công tác mà system phải đảm nhiệm.&lt;br /&gt;&lt;br /&gt;c. tái biên dịch để loại bỏ những "drivers" không được dùng và có thể gây "hiểu lầm" cho kernel, tạo ra trường hợp máy có những triệu chứng hoạt động thiếu ổn định và hay gây lỗi.&lt;br /&gt;&lt;br /&gt;d. tái biên dịch kernel để thử nghiệm một chức năng hoặc một module mình vừa tạo ra. Trường hợp này không nhiều như các trường hợp trên nhưng cũng nằm trong các lý do phổ biến.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. Cấu trúc và quy định phiên bản của Linux kernel&lt;/b&gt;&lt;br /&gt;Phiên bản của Linux có quy định rất đơn giản và dễ nhớ. Vấn đề này cần nắm rõ trước khi chọn một phiên bản nào đó của Linux kernel để vá và biên dịch.&lt;br /&gt;&lt;br /&gt;Phiên bản của Linux bao gồm ba nhóm số tách ra bởi các dấu chấm. Ví dụ: 2.4.26&lt;br /&gt;&lt;br /&gt;Số thứ nhất: &lt;b&gt;2&lt;/b&gt; là phiên bản&lt;br /&gt;Số thứ nhì: &lt;b&gt;4&lt;/b&gt; là chỉ định cho tình trạng phiên bản. Nếu số này là số chẵn, nó chỉ định cho phiên bản ổn định (stable), có thể dùng cho môi trường production. Nếu số này là số lẻ, nó chỉ định cho phiên bản không ổn định, nó thường dùng trong môi trường đang phát triển (development). Các kernel thuộc dạng này thường có nhiều bugs và không ổn định. Nếu dùng các phiên bản này để tìm bugs và thông báo cho nhóm phát triển Linux kernel thì đây là điều rất tốt. Không nên dùng phiên bản development cho môi trường production.&lt;br /&gt;Số thứ ba: &lt;b&gt;26&lt;/b&gt; là chỉ định cho số hiệu phát hành của một phiên bản Linux kernel. Một phiên bản ổn định của một Linux kernel có thể có nhiều số hiệu phát hành khác nhau.&lt;br /&gt;&lt;br /&gt;Đây là các quy định chung cho dạng Linux kernel "vanilla" có nghĩa là ứng dụng cho các phiên bản kernel từ &lt;a target="_blank" href="http://www.kernel.org/"&gt;http://www.kernel.org&lt;/a&gt;, các phiên bản kernel được điều chỉnh bởi mỗi distribution có những điểm dị biệt. Có nhiều Linux distribution xử dụng số hiệu con (extra-version) cho phiên bản kernel họ đã điều chỉnh. Ví dụ RedHat có những cập nhật phụ cho các kernel như: 2.4.20-8 chẳng hạn. Điều cần nắm ở đây là chỉ nên xử dụng phiên bản ổn định (stable) của Linux kernel (số chẵn ở giữa) cho môi trường production và dùng phiên bản thử nghiệm (development) của Linux kernel (số lẻ) cho môi trường thử nghiệm và phát triển.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4. Đòi hỏi tối thiểu trong việc tái biên dịch Linux kernel&lt;/b&gt;&lt;br /&gt;Trước khi bắt tay vào việc tái biên dịch Linux kernel, điều cần thiết là phải có đủ chỗ chứa trên disk. Ít nhất là phải đủ chỗ chứa cho mã nguồn (trước và sau khi xả nén), chỗ chứa để cài kernel và các modules mới sau khi biên dịch.&lt;br /&gt;&lt;br /&gt;Đòi hỏi quan trọng khác là phải có một bộ công cụ cần thiết và đúng phiên bản, không thể biên dịch được kernel nếu không thoả mãn yêu cầu này. Phiên bản cho bộ công cụ với mỗi series kernel khác nhau. Nên nhớ, nhóm phát triển kernel &lt;b&gt;yêu cầu&lt;/b&gt; bạn phải có đúng phiên bản của các công cụ để đảm bảo việc biên dịch kernel thành công.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4.1 Đòi hỏi cho Linux kernel 2.4.x&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Đồ nghề        Phiên bản tối thiểu    Cách xác định phiên bản có trên máy&lt;/b&gt;&lt;br /&gt;Gnu C                2.91.66         # gcc --version&lt;br /&gt;Gnu make          3.77            # make --version&lt;br /&gt;binutils               2.9.1.0.25      # ld -v&lt;br /&gt;util-linux             2.10o           # fdformat --version&lt;br /&gt;modutils             2.4.2           # insmod -V&lt;br /&gt;e2fsprogs           1.19            # tune2fs&lt;br /&gt;reiserfsprogs      3.x.0b          # reiserfsck 2&gt;&amp;1|grep reiserfsprogs&lt;br /&gt;pcmcia-cs           3.1.21          # cardmgr -V&lt;br /&gt;PPP                    2.4.0           # pppd --version&lt;br /&gt;isdn4k-utils         3.1pre1         # isdnctrl 2&gt;&amp;amp;1|grep version&lt;br /&gt;&lt;br /&gt;Tham khảo thêm chi tiết các công cụ này và địa chỉ để tải các công cụ cho đúng (ít nhất phải cùng phiên bản đã cung cấp ở trên hoặc mới hơn) trong hồ sơ ./Documentation/changes của mã nguồn kernel bạn đang dự tính biên dịch.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4.2 Đòi hỏi cho Linux kernel 2.6.x&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Đồ nghề        Phiên bản tối thiểu    Cách xác định phiên bản có trên máy&lt;/b&gt;&lt;br /&gt;Gnu C                      2.95.3           # gcc --version&lt;br /&gt;Gnu make                3.78             # make --version&lt;br /&gt;binutils                     2.12             # ld -v&lt;br /&gt;util-linux                   2.10o            # fdformat --version&lt;br /&gt;module-init-tools       0.9.10           # depmod -V&lt;br /&gt;e2fsprogs                 1.29             # tune2fs&lt;br /&gt;jfsutils                      1.1.3            # fsck.jfs -V&lt;br /&gt;reiserfsprogs             3.6.3            # reiserfsck -V 2&gt;&amp;1|grep reiserfsprogs&lt;br /&gt;xfsprogs                   2.1.0            # xfs_db -V&lt;br /&gt;pcmcia-cs                 3.1.21           # cardmgr -V&lt;br /&gt;quota-tools               3.09             # quota -V&lt;br /&gt;PPP                          2.4.0            # pppd --version&lt;br /&gt;isdn4k-utils               3.1pre1          # isdnctrl 2&gt;&amp;amp;1|grep version&lt;br /&gt;nfs-utils                    1.0.5            # showmount --version&lt;br /&gt;procps                      3.1.13           # ps --version&lt;br /&gt;oprofile                     0.5.3            # oprofiled --version&lt;br /&gt;&lt;br /&gt;Tham khảo thêm chi tiết các công cụ này và địa chỉ để tải các công cụ cho đúng (ít nhất phải cùng phiên bản đã cung cấp ở trên hoặc mới hơn) trong hồ sơ ./Documentation/changes của mã nguồn kernel bạn đang dự tính biên dịch.&lt;br /&gt;&lt;br /&gt;Nếu phiên bản của các công cụ trên máy cũ hơn các phiên bản đưa ra ở trên, bạn &lt;b&gt;cần phải&lt;/b&gt; tải phiên bản mới (đã biên dịch) từ website của distribution nào bạn đang dùng. Bạn cũng có thể chọn cách tải mã nguồn của từng công cụ về biên dịch lại. Cách này mất thời gian hơn rất nhiều và chỉ thích hợp cho những ai đã quen thuộc với vấn đề biên dịch mã nguồn trên Linux. Lợi điểm của cách này là bạn tạo cho mình một bộ công cụ rất "sạch" vì đã biên dịch theo ý, thích hợp với môi trường của máy (và vừa đủ).&lt;br /&gt;&lt;br /&gt;Đối với IA64 architecture, bạn cần GCC 64bit compliant compiler, nên tham khảo chi tiết ở:&lt;br /&gt;&lt;a target="_blank" href="http://gcc.gnu.org/install/specific.html"&gt;http://gcc.gnu.org/install/specific.html&lt;/a&gt; (nếu bạn may mắn có một con IA64 để thử :)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;5. Xác định cấu hình (hardware) của máy&lt;/b&gt;&lt;br /&gt;Phần lớn người dùng bình thường ít khi quan tâm đến cấu hình của máy ngoại trừ có nhu cầu cụ thể. Ngay cả những ai dùng Linux đã lâu và không cần phải tái biên dịch kernel, cũng ít khi quan tâm đến cấu hình hardware của máy. Dù có biết nhiều hay ít về cấu hình hardware của máy mình dùng, bạn vẫn phải thu thập thông tin &lt;b&gt;chính xác&lt;/b&gt; của cấu hình trước khi bắt tay vào việc điều chỉnh kernel build configuration.&lt;br /&gt;&lt;br /&gt;Giả định mọi chỉnh lý đã ổn định và làm việc tốt đẹp (do installer tự detect trong khi cài Linux hay do bạn phải điều chỉnh lại), bạn cần tái biên dịch Linux kernel và cần thâu thập thông tin về cấu hình của máy, hai lệnh sau cung cấp các chi tiết hardware có trên máy:&lt;br /&gt;&lt;b&gt;# /sbin/lspci&lt;/b&gt; để liệt kê trọn bộ những PCI "card" đang gắn vào máy. Lệnh này liệt kê trọn bộ các "card" đang trực tiếp làm việc trên máy, hardware version và model của chúng.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;# cat /proc/cpuinfo&lt;/b&gt; để xem chi tiết CPU của máy là loại gì. Nếu Linux distribution bạn dùng không dùng /proc filesystem thì bạn có thể dùng lệnh &lt;b&gt;# dmesg&lt;/b&gt; để thu thập thông tin về hardware trên máy của mình. Ngoài ra, lệnh &lt;b&gt;lsmod&lt;/b&gt; cũng ít nhiều giúp bạn xác định các modules đang được dùng trên máy và tên của các modules này.&lt;br /&gt;&lt;br /&gt;Những thông tin thâu thập được ở đây &lt;b&gt;hết sức quan trọng&lt;/b&gt; trong giai đoạn điều chỉnh kernel build configuration. Nó giúp bạn xác định các chọn lựa đúng cho cấu hình máy, tránh đi những trở ngại có thể rất mất thời gian sau này.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;6. Các bước chuẩn bị&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;6.1 Tạo một bootable floppy disk dùng kernel đang chạy&lt;/b&gt;&lt;br /&gt;Đây là một bước cần thiết đề phòng sự cố gì đó khiến bạn không thể boot vào Linux system sau khi cài kernel mới. Trường hợp này hiếm khi xảy ra trong quá trình biên dịch kernel và cài kernel mới nếu bạn thực hiện và điều chỉnh đúng. Những sự cố với bootloader (LILO hoặc GRUB) ít thấy xảy ra vì bootloader đã được thiết lập hoàn chỉnh trước khi cập nhật kernel. Phần lớn giai đoạn tái điều chỉnh config của LILO hoặc GRUB không chính xác tạo trở ngại. Vấn đề này sẽ được đề cập sau. Trước mắt chúng ta cần tạo một "bootable floppy disk".&lt;br /&gt;&lt;br /&gt;Có rất nhiều cách để tạo một bootable floppy lấy từ kernel hiện đang chạy trên máy. Thay vì trình bày nhiều cách khác nhau cho việc tạo bootable floppy disk, ở đây tôi chỉ đề cập đến phương thức đơn giản nhất. Cách dễ nhất có lẽ là cách dùng &lt;b&gt;mkbootdisk&lt;/b&gt;. Đây là một binary được cài mặc định trên các RedHat distribution và hầu hết các distribution dựa RedHat. Nếu binary này không hiện diện trên máy, bạn có thể tải mã nguồn về và biên dịch cho distribution mình đang dùng. Chạy lệnh:&lt;br /&gt;&lt;b&gt;# mkbootdisk --device /dev/fd0 `uname -r`&lt;/b&gt;, trong đó&lt;br /&gt;&lt;b&gt;`uname -r`&lt;/b&gt; là lệnh ngầm để lấy phiên bản kernel hiện dùng trên máy. Nếu không muốn phiên bản này, bạn có thể gõ vào phiên bản nào đó theo ý (tất nhiên là phiên bản kernel này phải hiện hữu trên system).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;/dev/fd0&lt;/b&gt; là "device" chỉ cho đĩa mềm thứ nhất trên máy (tương tự như drive A: trên DOS). Bạn phải chọn đúng "device" thì mới có dữ liệu viết vào đĩa mềm mình muốn tạo.&lt;br /&gt;&lt;br /&gt;Quy trình này chỉ mất khoảng vài phút. Sau khi tạo bootable floppy disk ở trên, bạn nên dùng nó để thử boot vào Linux trước khi thực hiện các bước kế tiếp. Nên nhớ phải chỉnh BIOS để cho phép máy boot từ A:&lt;br /&gt;&lt;br /&gt;Ở trang:&lt;br /&gt;&lt;a target="_blank" href="http://www.yolinux.com/TUTORIALS/LinuxTutorialRecoveryAndBootDisk.html"&gt;http://www.yolinux.com/TUTORIALS/Lin...Disk.html&lt;/a&gt;&lt;br /&gt;có các hướng dẫn tạo disk cấp cứu rất hay. Bạn nên tham khảo thêm nếu trên máy mình dùng không có sẵn &lt;b&gt;mkbootdisk&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;6.2 Tải mã nguồn&lt;/b&gt;&lt;br /&gt;Mã nguồn của Linux kernel cả stable lẫn development có rất nhiều nơi trên Internet. Nên vào trang trung tâm của Linux kernel ở &lt;a target="_blank" href="http://www.kernel.org/"&gt;http://www.kernel.org&lt;/a&gt; và tham khảo danh sách "mirrors" để tìm nơi "gần" chỗ mình cư ngụ nhất để tải về. Nơi "gần" không nhất thiết là "gần" theo phương diện địa lý mà nên chọn "gần" nhất dựa trên "ping time". Chịu khó lấy vài địa chỉ trên mirror và ping những địa chỉ này để chọn lấy nơi có ping time ngắn nhất mà download. Bằng cách sẽ giúp bạn đỡ mất thời gian và tiện cho vấn đề chia xẻ băng thông.&lt;br /&gt;&lt;br /&gt;Có nhiều cách tải mã nguồn. Bạn có thể dùng browser để tải qua http hoặc dùng một ftp client nào đó để tải qua ftp. Bạn cũng có thể dùng &lt;b&gt;wget&lt;/b&gt; để download. Có lẽ đây là cách tiện nhất và nhanh nhất nếu biết rõ địa chỉ và đường dẫn đến gói mình muốn download. Ví dụ:&lt;br /&gt;&lt;b&gt;$ wget &lt;a target="_blank" href="http://www.kernel.org/pub/linux/kernel/v2.4/linux-2.4.26.tar.bz2"&gt;http://www.kernel.org/pub/linux/kern...6.tar.bz2&lt;/a&gt;&lt;/b&gt; (trong trường hợp này, gói cụ thể cần tải là linux-2.4.26.tar.bz2).&lt;br /&gt;&lt;br /&gt;Mã nguồn ổn định của Linux kernel được nén ở hai dạng khác nhau: dạng có đuôi là .gz (dùng GNUzip để nén) và dạng có đuôi .bz2 (dùng bzip2 để nén). Thông thường cả hai tiện ích nén / xả nén trên đều có sẵn trong các Linux distribution thông dụng. Nếu không có sẵn trên máy thì tìm trong trong CD của distribution (tham khảo thêm tài liệu của distribution mình dùng cho cách cài thêm software trên máy) hoặc tải về từ:&lt;br /&gt;- &lt;a target="_blank" href="http://www.gzip.org/"&gt;http://www.gzip.org/&lt;/a&gt; cho GNUzip&lt;br /&gt;- &lt;a target="_blank" href="http://sources.redhat.com/bzip2/"&gt;http://sources.redhat.com/bzip2/&lt;/a&gt; cho bzip2&lt;br /&gt;&lt;/kernerl_src&gt;&lt;/kernel_src&gt;&lt;kết style="font-family: verdana;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;hnd,&gt;&lt;/hnd,&gt;&lt;/kết&gt;&lt;/span&gt;&lt;span style=";font-family:verdana;font-size:85%;"  &gt;&lt;kết&gt;&lt;/kết&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:verdana;font-size:85%;"  &gt;&lt;hnd,&gt;&lt;/hnd,&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;kết style="font-family: verdana;"&gt;&lt;hnd,&gt;&lt;kernel_src&gt;&lt;kernerl_src&gt;&lt;br /&gt;&lt;hnd,&gt;&lt;/hnd,&gt;&lt;/kernerl_src&gt;&lt;/kernel_src&gt;&lt;/hnd,&gt;&lt;/kết&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37459183-6748638033645900735?l=conmale.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://conmale.blogspot.com/feeds/6748638033645900735/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37459183&amp;postID=6748638033645900735' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/6748638033645900735'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/6748638033645900735'/><link rel='alternate' type='text/html' href='http://conmale.blogspot.com/2007/05/bin-dch-linux-kernel-phn-1.html' title='Biên dịch Linux kernel - phần 1'/><author><name>conmale</name><uri>http://www.blogger.com/profile/16598933828282382048</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/-2pIWb2iUysc/TzSYz5aVJYI/AAAAAAAAAAQ/BCWx8yVHmbU/s220/me.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37459183.post-421175885036225936</id><published>2007-04-19T12:40:00.000+10:00</published><updated>2007-06-20T20:01:09.957+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Social'/><title type='text'>Nhìn lại từ năm 2000...</title><content type='html'>&lt;span style="font-family:verdana;font-size:85%;"&gt;Đầu năm 2000, tôi về thăm VN. Đó là lần đầu tiên tôi có dịp tiếp xúc với các anh em trong ngành CNTT ở VN.&lt;br /&gt;&lt;br /&gt;Năm đó, khi quay lại Úc, tôi bắt đầu tìm hiểu kỹ hơn về tình hình CNTT tại VN bằng cách đọc tin tức và tham gia một số diễn đàn thảo luận tin học.&lt;br /&gt;&lt;br /&gt;Diễn đàn đầu tiên tôi vào đó là diễn đàn... gì đó của VDC (tôi quên bẵng cái tên). Tôi sinh hoạt ở đây đúng một tuần và không ghé lại nữa bởi vì tôi nhiều lần bị sự cố với việc đăng nhập. Mặc dù đã gởi e-mail đến nhóm hỗ trợ, họ không bao giờ trả lời. Hơn nữa, lần đầu tiên sinh hoạt ở một diễn đàn tiếng Việt (và điều hợp rất kém), tôi thấy hết sức lạ lẫm bởi vì tôi không hề nhận được một lần "cám ơn" từ thành viên trên diễn đàn này mặc dù tôi tẩn mẩn trả lời một số bài viết hết sức chi tiết và kỹ lưỡng. Đành vậy, cái duyên với VDC forum thật ngắn ngủi.&lt;br /&gt;&lt;br /&gt;Sau đó một thời gian ngắn, tôi tìm ra một diễn đàn tiếng Việt có tên là diendantinhoc.org (xuyên qua search engine). Rút kinh nghiệm lần trước, lần này tôi lượn lờ bên ngoài, quan sát cách sinh hoạt và tổ chức của diễn đàn khá lâu trước khi tôi đăng ký tài khoản chính thức để tham gia. Đây là diễn đàn tôi sinh hoạt lâu nhất. Cho đến nay tôi vẫn còn sinh hoạt ở diễn đàn này và trông lo khoản "cơ sở hạ tầng" của nó. Trong suốt mấy năm sinh hoạt với diendantinhoc.org, sau đổi tên domain chính thức thành vninformatics.com (tôi có may mắn chọn cái domain này và anh em nhất trí với nó), tôi viết và dịch khá nhiều tài liệu.&lt;br /&gt;&lt;br /&gt;Khoảng 2003, ngoài vninformatics.com, tôi tham gia sinh hoạt với một diễn đàn khác có tên là vnsecurity.net. Đây là một diễn đàn không lớn như vninformatics.com nhưng anh em ở đây chuyên về bảo mật và bởi thế, diễn đàn này khá đặc biệt. Không may, diễn đàn vnsecurity.net bất thình lình đóng cửa (vì lý do nào đó, cho đến nay tôi cũng chẳng rõ).&lt;br /&gt;&lt;br /&gt;Giữa năm 2004, tôi bắt đầu tham gia diễn đàn HVAOnline với tư cách thăm dò. Tôi biết HVAOnline từ những năm 2001, 2002 nhưng không tham gia vì tính lộn xộn của nó vào những năm ấy. Mãi đến đầu tháng mười năm 2004, tôi mới chính thức góp sức vào việc "chống" DDoS mà HVA hứng chịu một thời gian dài. Tôi được biết đến bằng 2 cái nick name: hnd (ở diễn đàn vninformatics.com) và conmale (ở diễn đàn hvaonline.net).&lt;br /&gt;&lt;br /&gt;Cho đến nay, tôi vẫn thường xuyên sinh hoạt ở hai diễn đàn: vninformatics.com (diendantinhoc.org) và hvaonline.net.&lt;br /&gt;&lt;br /&gt;Tôi dự định sẽ thâu thập lại trọn bộ những bài viết, bài dịch mà tôi đã thực hiện trong hơn 6 năm qua để đưa lên blog này (cho mục đích lưu trữ - vì tôi tin rằng google khó mà chết ;)).&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37459183-421175885036225936?l=conmale.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://conmale.blogspot.com/feeds/421175885036225936/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37459183&amp;postID=421175885036225936' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/421175885036225936'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/421175885036225936'/><link rel='alternate' type='text/html' href='http://conmale.blogspot.com/2007/04/nhn-li-t-nm-2000.html' title='Nhìn lại từ năm 2000...'/><author><name>conmale</name><uri>http://www.blogger.com/profile/16598933828282382048</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/-2pIWb2iUysc/TzSYz5aVJYI/AAAAAAAAAAQ/BCWx8yVHmbU/s220/me.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37459183.post-2156599683490494341</id><published>2007-02-12T10:48:00.000+11:00</published><updated>2007-06-20T20:01:34.237+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Social'/><title type='text'>Chuyện gì xảy ra sau đó?</title><content type='html'>&lt;span style="font-family:verdana;font-size:85%;"&gt;Tôi nhận khá nhiều e-mail, PM, offline messages.... "hỏi thăm" chuyện gì xảy ra sau đó, sau cái ngày lão sếp sồng sộc bước vào phòng làm việc của bọn tôi và phán rằng: &lt;span style="font-style: italic;"&gt;"sao tụi mày không tìm cách giới hạn chỉ cho phép các chi nhánh sử dụng dịch vụ ftp"&lt;/span&gt;. Chuyện là thế này....&lt;br /&gt;&lt;br /&gt;Bọn tôi lân la các IRC channels và hỏi han về cách thức làm sao giới hạn một hoặc nhiều IP truy cập đến một dịch vụ do mình làm chủ. Thời ấy IRC toàn là dân cyber-junky hay là nerd thứ thiệt lai vãng cho nên một câu hỏi được đặt ra là có cả đống câu trả lời, bàn tán, đề nghị... nếu như câu hỏi ấy chứng tỏ mức quan tâm đúng mức và thể hiện tính nghiêm túc của nó &lt;span style="font-style: italic;"&gt;(chả bù ngày nay diễn đàn nào cũng helppp meeee... kíu kíu.... và chẳng buồn giải thích rõ vấn đề)&lt;/span&gt;. Phần lớn các hồi đáp là &lt;span style="color: rgb(204, 51, 204);"&gt;"ấn định user account được phép login"&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Một ngày đẹp trời không lâu sau đó, có một gã trên IRC loan báo &lt;/span&gt;&lt;span style="font-family:verdana;font-size:85%;"&gt;&lt;a href="http://www.porcupine.org/wietse/"&gt;Wietse Zweitze Venema&lt;/a&gt;  (được biết đến nhiều với cái tên &lt;span style="font-weight: bold;"&gt;Wietse Venema&lt;/span&gt;) đã ra mắt một giải pháp gọi là "tcp wrapper" nhưng ít người biết đến và gã tuyên bố rằng với giải pháp này, hệ thống *nix của bạn sẽ vững như... đồng. Paper nguyên thuỷ về tcp wrapper mà Venama đã viết còn lưu ở &lt;a href="http://www.vtcif.telstra.com.au/pub/docs/security/tcp_wrapper.txt"&gt;đây&lt;/a&gt; và nhiêu nơi khác trên mạng. Hiện nay trường Đại học Indiana vẫn còn bảo trì "tcp wrapper" ở &lt;a href="http://itso.iu.edu/TCP_Wrappers"&gt;đây&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Bọn tôi mừng như bắt được vàng và hối hả tìm mã nguồn, tải về và biên dịch để dùng thử. Thời ấy chẳng có chuyện gì là dễ dàng. Tải nguồn về, bọn tôi khám phá ra phải cần C compiler để biên dịch nhưng C compiler chẳng có sẵn và muốn có thì phải trả thêm $ (vì không được cung cấp miễn phí). Chẳng bù ngày nay compiler tràn ngập trên mạng. Bọn tôi phải thuyết phục lão xếp chi $ để mua thêm bộ compiler. Nếu tôi nhớ không sai thì hồi ấy công ty phải mở hầu bao ra và chi mấy ngàn đô Úc &lt;span style="font-weight: bold; color: rgb(255, 204, 51);"&gt;-1-&lt;/span&gt; cho bộ C compiler trên Solaris. Gần một tháng sau bọn tôi mới nhận được CD từ bên Mẽo gởi sang.&lt;br /&gt;&lt;br /&gt;Hăm hở cài bộ compiler lên test server, bọn tôi thử biên dịch... Ôi thôi, lỗi tè le. Nào là thiếu thư viện, rồi lại thư viện không tương thích, khai báo chỗ này sai, khai báo chỗ kia thiếu. Bọn tôi, một lũ admin tay ngang, chẳng biết bao nhiêu về C, chẳng biết link thư viện là cái quái quỷ gì. Thế là lại lò dò vào IRC hỏi. Dân cư trên IRC cực tốt, họ giúp cho đủ thứ, chỉ vẽ đủ điều. Thế nhưng, bọn tôi phải ra tiệm sách kiếm mấy cuốn sách về C để mà "bồi bổ".&lt;br /&gt;&lt;br /&gt;Loay hoay cả tháng trời, bọn tôi biên dịch thành công, cài đặt thành công. Chỉ vỏn vẹn có mấy dòng config cho &lt;span style="font-weight: bold;"&gt;inetd&lt;/span&gt;, tạo và thêm giá trị cho hai cái &lt;span style="font-weight: bold;"&gt;hosts.deny&lt;/span&gt; và &lt;span style="font-weight: bold;"&gt;hosts.allow&lt;/span&gt;. Thế là bọn tôi lại... phè cánh nhạn.&lt;br /&gt;&lt;br /&gt;Cuối tuần lễ đầu, cả bọn in ra một đống log (trong syslog) để báo cáo với lão xếp "thành quả lớn lao". Lão gật gù và nói &lt;span style="font-style: italic;"&gt;"Được lắm. Chả bỏ mấy ngàn bạc để mua cái compiler quỷ quái gì đó"&lt;/span&gt;. Thế rồi, lão lại nói tiếp: &lt;span style="font-style: italic;"&gt;"bọn bây có bảo đảm 100% là không còn bị sự cố nữa không?"&lt;/span&gt;. Mấy thằng tôi tắc tị, mặt xanh dờn, nhìn nhau và... ú ớ vì chẳng biết nên trả lời lão thế nào. Tôi đánh bạo trả lời lão: &lt;span style="font-style: italic;"&gt;"để bọn tôi xem xét lại rồi sẽ báo cáo chi tiết cho ông sau."&lt;/span&gt;. Lão ầm ừ rồi kêu bọn tôi tan hàng. Có lẽ do dáng điệu tiu nghỉu của bọn tôi thảm não quá, lão nói với theo: &lt;span style="font-style: italic;"&gt;"Bọn bây cần gì cứ cho tao biết. Ráng sao cho yên là được, không thì chẳng những mông của tụi mày bị dập mà mông của tao cũng lãnh đủ"&lt;/span&gt; &lt;span style="font-weight: bold; color: rgb(255, 204, 102);"&gt;-2-&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Bọn tôi về phòng và lại log vào IRC, channel của sự sống sót (theo cách gọi của bọn tôi thời ấy "survival channel").&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Chú thích:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 204, 102);"&gt;-1-&lt;/span&gt;: những năm đầu thập niên 90, đồng đô Úc chỉ thua đô Mẽo vài xu, giá trị  của hai đồng đô ngang ngửa nhau.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 204, 102);"&gt;-2-&lt;/span&gt;: tôi còn nhớ nguyên văn là &lt;span style="font-style: italic;"&gt;"not only your asses get kicked but mine too"&lt;/span&gt;.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37459183-2156599683490494341?l=conmale.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://conmale.blogspot.com/feeds/2156599683490494341/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37459183&amp;postID=2156599683490494341' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/2156599683490494341'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/2156599683490494341'/><link rel='alternate' type='text/html' href='http://conmale.blogspot.com/2007/02/chuyn-g-xy-ra-sau.html' title='Chuyện gì xảy ra sau đó?'/><author><name>conmale</name><uri>http://www.blogger.com/profile/16598933828282382048</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/-2pIWb2iUysc/TzSYz5aVJYI/AAAAAAAAAAQ/BCWx8yVHmbU/s220/me.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37459183.post-116528562760091041</id><published>2006-12-05T12:01:00.000+11:00</published><updated>2007-06-20T20:02:45.327+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Social'/><title type='text'>Từ đâu tôi quan tâm đến bảo mật?</title><content type='html'>&lt;span style=";font-family:verdana;font-size:85%;"  &gt;Có lần (đúng ra là nhiều lần) tôi "bị" hỏi rằng: &lt;span style="font-style: italic;"&gt;"anh đã đến với bảo mật như thế nào?"&lt;/span&gt;. Tôi cười xoà và trả lời tôi đã "đến với nó" như thế này:&lt;br /&gt;&lt;br /&gt;Đó là năm 1992, khi tôi còn làm việc với một công ty chuyên sản xuất và phát hành CD, sách, tạp chí... Công ty ấy đứng ở vị trí "top three" trong ngành này ở Úc vào những năm đó.&lt;br /&gt;&lt;br /&gt;Khi mà thời Internet còn là thứ xa vời và những ai may mắn có được một chiếc modem 9600 bauds để gọi vào một BBS, chúng tôi "bị" bổ nhiệm thiết kế một hệ thống chuyển gởi hồ sơ giữa các chi nhánh bởi vì công ty này có văn phòng khắp nơi từ Tân Tây Lan sang Úc, trải dài sang Thái Lan, Ấn Độ (và một khoảng thời gian có mặt ở Hồng Kông).&lt;br /&gt;&lt;br /&gt;Mọi chuyện diễn ra khá suông sẻ sau 5 tuần sắp đặt, điều chỉnh, bay (bằng máy bay) đến các chi nhánh để &lt;/span&gt;&lt;span style=";font-family:verdana;font-size:85%;"  &gt;cài server (&lt;a href="http://www.sun.com/software/solaris/"&gt;Solaris&lt;/a&gt;),&lt;/span&gt;&lt;span style=";font-family:verdana;font-size:85%;"  &gt; kết nối, điều chỉnh hệ thống. Telstra lúc ấy là công ty viễn thông duy nhất ở Úc cung cấp &lt;a href="http://en.wikipedia.org/wiki/ISDN"&gt;ISDN&lt;/a&gt; và chúng tôi thật "phê" khi được vọc đường dây 64K lần đầu tiên (128K dual-line cho các văn phòng lớn). Dữ liệu được chuyển tải bằng ftp giữa các văn phòng và được điều tác bằng một chương trình home-grown (tự viết) bằng Perl (hèm... yucky).&lt;br /&gt;&lt;br /&gt;Sau sáu tháng hoạt động đều đặn, không chút sự cố, tai nạn bắt đầu xảy ra. Một ngày "đẹp trời", ông sếp hầm hầm bước vào data room của chúng tôi và vứt xuống bàn một tờ thanh toán với số tiền kinh khủng. Tôi còn nhớ mang máng hình như là hai mươi mấy ngàn đô la. Lão sếp "gầm rú" giận dữ: &lt;span style="font-style: italic;"&gt;"tại sao trước giờ tháng nào cũng dưới năm ngàn một tháng, tháng này gần ba chục ngàn tiền đường dây? Tụi bây liệu mà điều tra và fix ngay lập tức"&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Bọn tôi tiu nghỉu thoát ra khỏi IRC channel (hèm... thời đó quả là hoàng kim, ngồi server room máy điều hoà không khí, dùng dual-channel ISDN để IRC, chừng nào có chuyện thì mới làm việc ;)) và gọi điện cho đám Telstra để bắt đầu điều tra sự thể. Sau vài giờ liên lạc, bọn tôi được biết rằng dung lượng đi xuyên qua đường dây ISDN tăng gấp năm lần bình thường. Hối hả trace ngược lại số lượng job đã queue và transfered, cộng trừ nhân chia... bọn tôi thấy rằng số lượng dữ liệu có gia tăng nhưng không thể nào đến mức 5 lần tháng trước.&lt;br /&gt;&lt;br /&gt;Bọn tôi quyết định yêu cầu đám Telstra cung cấp bản tường trình chi tiết số lượng băng thông được sử dụng theo từng tháng. Từ bản tường trình, điều rõ ràng là số lượng băng thông gia tăng theo cấp số, đặc biệt từ nửa tháng trước cho đến tháng cuối cùng. Không dám nghĩ rằng Telstra tính hoá đơn sai vì họ có đầy đủ bằng chứng mức sử dụng, bọn tôi lại quay ngược về đống logs, trace số lượng jobs ra vào và đi đến kết luận: it nhất 70% dung lượng băng thông được dùng cho việc gì đó bí ẩn.&lt;br /&gt;&lt;br /&gt;Thời ấy, chẳng đứa nào trong bọn tôi có chút ý niệm gì về bảo mật. Chẳng bao giờ nghĩ đến src_ip, dst_ip, chẳng bao giờ nghĩ rằng dịch vụ ftp đã có ấn định username / password mà có thể suy suyển. Thế nhưng, sau nhiều giờ sục tìm, bọn tôi nhận ra rằng có hàng trăm IP addresses truy cập ftp server của chúng tôi. Các IP này đi từ US và Europe là chính (lúc ấy chưa có ISDN ở Ấn và Thái). Tìm sâu hơn, chúng tôi phát hiện ra một thư mục chứa đủ thứ đồ "hàng xén" do ai đó upload tự lúc nào. Thư mục này có dung lượng mấy chục Mb (thời ấy, mấy chục Mb rất lớn và băng thông được tính theo K). Kiểm tra lại user account và password, mọi thứ đều ổn.... lạ nhỉ?&lt;br /&gt;&lt;br /&gt;Bọn tôi hết phương cách bèn gởi sự thể đến SUN nhờ họ hỗ trợ. Sau hơn tuần lễ gọi điện liên tục, thảo luận trực tiếp với CA (Sun based ở California), chúng tôi nhận được một CD có bản vá cho OS và dịch vụ FTP. Tất nhiên là thư mục chứa hàng xén kia bị xoá và hoá đơn lão sếp nhận trở lại bình thường. Đám Telstra đồng ý cắt hoá đơn ấy còn 1/2 vì không phải hoàn toàn lỗi của bọn tôi (khoảng 10 ngàn thời đó, thời giá bây giờ có lẽ khoảng 100 ngàn đô).&lt;br /&gt;&lt;br /&gt;Sau này, tôi tự tìm hiểu (vì thắc mắc và vì hỏi đám SUN lý do, họ không thèm giải thích) thì mới biết rằng dịch vụ FTP ở phiên bản ấy có lỗi cho phép by-pass authentication trên cổng 21 và đi thẳng vào data port ở cổng 20. "Ai đó" có thể upload file thẳng qua cổng 20 dễ dàng :). Thông tin về cái thư mục "hàng xén" kia trên FTP server của bọn tôi được phán tán và lan truyền trên IRC, BBS thời đó và thiên hạ tha hồ vào download. Âu đó cũng là duyên số cho tôi nảy ra thói tò mò bảo mật.&lt;br /&gt;&lt;br /&gt;Một ngày đẹp trời không lâu sau đó, lão sếp lại xuất hiện và chỉ hỏi một câu gọn lỏn: &lt;span style="font-style: italic;"&gt;"bọn bây sao không tìm cách hạn chế chỉ cho các chi nhánh của công ty truy cập cái FTP server?"&lt;/span&gt; rồi biến mất. Đó là cơ duyên tiếp theo để tôi tìm hiểu về một cơ chế có khả năng cản lọc (firewall) và &lt;a href="http://www.fwtk.org/"&gt;tis&lt;/a&gt; là firewall đầu tiên tôi đụng đến (từ một đĩa mềm và 1 tập photocopy do một lão bên Mỹ gởi sang vào năm 1994) nhưng đây là chuyện khác.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37459183-116528562760091041?l=conmale.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://conmale.blogspot.com/feeds/116528562760091041/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37459183&amp;postID=116528562760091041' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/116528562760091041'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/116528562760091041'/><link rel='alternate' type='text/html' href='http://conmale.blogspot.com/2006/12/t-u-ti-quan-tm-n-bo-mt.html' title='Từ đâu tôi quan tâm đến bảo mật?'/><author><name>conmale</name><uri>http://www.blogger.com/profile/16598933828282382048</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/-2pIWb2iUysc/TzSYz5aVJYI/AAAAAAAAAAQ/BCWx8yVHmbU/s220/me.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37459183.post-116364667581413855</id><published>2006-11-16T13:14:00.000+11:00</published><updated>2007-06-20T15:25:29.133+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Social'/><title type='text'>Một kiểu nhìn về dữ liệu...</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;Tôi là &lt;span style="font-weight: bold; color: rgb(51, 204, 255);"&gt;a&lt;/span&gt;. Lũ bạn tôi, đứa thì tên &lt;span style="font-weight: bold; color: rgb(0, 204, 204);"&gt;1&lt;/span&gt;, đứa tên &lt;span style="font-weight: bold; color: rgb(0, 204, 204);"&gt;10&lt;/span&gt;, đứa tên &lt;span style="font-weight: bold; color: rgb(0, 204, 204);"&gt;3.5407059681495977512423785953907e+48&lt;/span&gt;, lại có đứa tên &lt;span style="font-weight: bold; color: rgb(0, 204, 204);"&gt;Nguyễn Văn Tèo&lt;/span&gt;, đứa thì mang tên &lt;span style="font-weight: bold; color: rgb(0, 204, 204);"&gt;t\u00ed&lt;/span&gt;, thậm chí có đứa mang tên là &lt;span style="font-weight: bold; color: rgb(0, 204, 204);"&gt;74 E8 6F.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:verdana;"&gt;Cùng nhau, chúng tôi rong ruổi qua những chặng đường mà người tạo ra chúng tôi muốn như thế.&lt;br /&gt;&lt;br /&gt;Chúng tôi, một đám dữ liệu vô tri giác, đi và về những khi bị gọi tên, hoà lẫn vào những lối đi, cưỡi lên các nhịp đập của tín hiệu, bị phân tán rã rời, bị ghép lại từ các mảnh, bị nhào trộn, nắn bóp, lọc chắt để rồi được sắp hàng trước đôi mắt của ai đó.&lt;br /&gt;&lt;br /&gt;Đôi khi chúng tôi hiền hoà và ích lợi.&lt;br /&gt;Lắm lúc chúng tôi tàn nhẫn và vô ích.&lt;br /&gt;&lt;br /&gt;Chúng tôi là nguyên nhân của thành công và thất bại. Chúng tôi chỉ là một đám dữ liệu vô tri vô giác.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37459183-116364667581413855?l=conmale.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://conmale.blogspot.com/feeds/116364667581413855/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37459183&amp;postID=116364667581413855' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/116364667581413855'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/116364667581413855'/><link rel='alternate' type='text/html' href='http://conmale.blogspot.com/2006/11/mt-kiu-nhn-v-d-liu.html' title='Một kiểu nhìn về dữ liệu...'/><author><name>conmale</name><uri>http://www.blogger.com/profile/16598933828282382048</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/-2pIWb2iUysc/TzSYz5aVJYI/AAAAAAAAAAQ/BCWx8yVHmbU/s220/me.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37459183.post-116315357595586470</id><published>2006-11-10T21:11:00.000+11:00</published><updated>2007-06-20T15:25:29.133+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Social'/><title type='text'>Opening.....</title><content type='html'>Once upon a time.... there was a place, nested deep deep in the Internet. It called "a place for friends..." and the story started.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37459183-116315357595586470?l=conmale.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://conmale.blogspot.com/feeds/116315357595586470/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37459183&amp;postID=116315357595586470' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/116315357595586470'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37459183/posts/default/116315357595586470'/><link rel='alternate' type='text/html' href='http://conmale.blogspot.com/2006/11/opening.html' title='Opening.....'/><author><name>conmale</name><uri>http://www.blogger.com/profile/16598933828282382048</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='http://3.bp.blogspot.com/-2pIWb2iUysc/TzSYz5aVJYI/AAAAAAAAAAQ/BCWx8yVHmbU/s220/me.jpg'/></author><thr:total>1</thr:total></entry></feed>
