tag:blogger.com,1999:blog-68858442024-03-07T11:17:59.438+07:00My Life As `Kamthorn'kamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.comBlogger102125tag:blogger.com,1999:blog-6885844.post-51697924378949969072012-09-25T15:13:00.000+07:002012-09-25T16:13:35.957+07:00~/.ssh/config<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd_DtkrKxVz32TWR_wADnkA2UL-UF99mlUJjh8yCNmOzHKsrvm1RD1Wpi-8eNP8S3QyG_yOuCU4Jvq4opW61dqVpdlDGJoT8TymKBH3-aKTXm7BZWk-eH-cX3rwhe4ZCwE9jDvOQ/s1600/ssh.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd_DtkrKxVz32TWR_wADnkA2UL-UF99mlUJjh8yCNmOzHKsrvm1RD1Wpi-8eNP8S3QyG_yOuCU4Jvq4opW61dqVpdlDGJoT8TymKBH3-aKTXm7BZWk-eH-cX3rwhe4ZCwE9jDvOQ/s1600/ssh.png" /></a></div>
เทคนิคการใช้ไฟล์ config ของ ssh ซึ่งเป็นไฟล์ค่าปรับแต่งสำหรับ ssh client บน Linux ซึ่งปกติเราจะระบุค่าต่างๆ ด้วย option ท้ายคำสั่ง ซึ่งบางครั้ง โฮสต์ปลายทางคนละโฮสต์ก็ต้องใช้ option ต่างกัน โดยเฉพาะ port ซึ่งมีหลายๆ โฮสต์ที่อาจจะเปลี่ยนหมายเลข port เป็นตัวอื่น ไม่ใช่ 22<br />
<br />
ให้สร้างไฟล์ <span style="font-family: "Courier New",Courier,monospace;">~/.ssh/config</span> ขึ้นมา (ปกติไม่มีไฟล์นี้อยู่)<br />
<br />
ใส่เนื้อหา<br />
<span style="font-family: "Courier New",Courier,monospace;">Host *</span><br />
<span style="font-family: "Courier New",Courier,monospace;">Protocol 2</span><br />
<span style="font-family: "Courier New",Courier,monospace;">ServerAliveInterval 300</span><br />
<span style="font-family: "Courier New",Courier,monospace;">ServerAliveCountMax 100</span><br />
<br />
เป็นการตั้งค่าแบบทั่วไป คือเวลาติดต่อกับทุก host ให้ใช้ protocol version 2 เท่านั้น และกำหนดให้ส่งแพกเกจเพื่อกระตุ้นให้มีการเชื่อมต่อทุก 5 นาที (300 วินาที) และส่งเป็นจำนวนสูงสุด 100 ครั้ง แสดงว่า ssh ที่เชื่อมจะไม่หลุดเป็นเวลา 500 นาที (8 ชั่วโมง 20 นาที) ถ้าไม่ตั้งแบบนี้บ่อยครั้ง ssh จะหลุดเร็วเกินไป<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">Host terminus</span><br />
<span style="font-family: "Courier New",Courier,monospace;">HostName terminus.abcdef.com</span><br />
<span style="font-family: "Courier New",Courier,monospace;">Port 18222</span><br />
<span style="font-family: "Courier New",Courier,monospace;">User ubuntu</span><br />
<br />
แบบนี้เป็นการตั้งค่าเฉพาะ host โดยจะกำหนดชื่อ host สำหรับใช้อ้างอิง เช่น terminus, แล้วระบุที่อยู่แบบเต็ม เช่น terminus.abcdef.com, กำหนด port เชื่อมต่อปลายทางเป็น 18222 ปกติคือ 22 ซึ่งไม่ระบุก็ได้เพราะเป็นค่าปริยาย แต่บางเซิร์ฟเวอร์อาจจะเลี่ยงมาใช้พอร์ตอื่นเพื่อลดการโจมตีแบบ portscan แล้ว attack ที่พอร์ต ssh, ระบุชื่อ user เป็น ubuntu ถ้าไม่ระบุมันจะใช้ชื่อ user เราที่เครื่อง local เอง หรือระบุที่ command line<br />
<br />
ถ้ามีโฮสต์อื่นก็เพิ่มเข้าไปทำนองเดียวกัน <br />
<br />
การตั้งค่าอื่นๆ มีอีกมาก ดูได้จากคำสั่ง<br />
<span style="font-family: "Courier New",Courier,monospace;">$ man ssh_config</span><br />
<br />
ถ้าเป็นเครื่องที่ใช้ร่วมกันหลายๆ คนหรือมีบริการอื่นรันอยู่เพื่อให้บริการบุคคลภายนอกด้วย หรือไม่แน่ใจ ควรเปลี่ยนสิทธิของไฟล์นี้ให้อ่านเขียนได้เฉพาะ user เราเองเท่านั้น โดยสั่ง<br />
<span style="font-family: "Courier New",Courier,monospace;">$ chmod go-rw ~/.ssh/config</span><br />
<span style="font-family: "Courier New",Courier,monospace;">$ ls -l ~/.ssh/config <br />-rw------- 1 kamthorn kamthorn 381 Aug 15 12:31 /home/kamthorn/.ssh/config </span><br />
<br />
การใช้งาน<br />
เดิมเราต้องสั่งด้วย<br />
<span style="font-family: "Courier New",Courier,monospace;">$ ssh -p 18222 ubuntu@terminus.abcdef.com</span><br />
<br />
พอเราตั้ง config ไว้แล้วก็แค่<br />
<span style="font-family: "Courier New",Courier,monospace;">$ ssh terminus</span><br />
<br />
เวลาจะ scp หรือ rsync ผ่าน ssh ก็จะง่ายขึ้น ไม่ต้องระบุพอร์ตอีกต่อไปkamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com0tag:blogger.com,1999:blog-6885844.post-41698732189984825472012-06-26T11:38:00.000+07:002012-06-26T11:38:46.390+07:0010 ซอฟต์แวร์เพื่อบริการ web site สำหรับทุกวันนี้<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTrhxoc8lZYKvys7trYt_YpAr0-mXAe5J6AM8v6IEdAnlMjGcUWSwi4nqqdt0hdRRDdcuaelfHfzvEga0CAn6E5GbCJHAbQtqxUsjg_e8_b7xjXrP9FOtHOIKS3xMWLMDOWcR3-Q/s1600/IMG_20120506_214657.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTrhxoc8lZYKvys7trYt_YpAr0-mXAe5J6AM8v6IEdAnlMjGcUWSwi4nqqdt0hdRRDdcuaelfHfzvEga0CAn6E5GbCJHAbQtqxUsjg_e8_b7xjXrP9FOtHOIKS3xMWLMDOWcR3-Q/s320/IMG_20120506_214657.jpg" width="320" /></a></div>
<br />
<h3>
Cores แกนหลักๆ ซึ่งก็คือ LAMP นั่นเอง</h3>
<ol>
<li>Linux ซึ่งปกติใช้ <a href="http://www.debian.org/">Debian</a> ตอนนี้รุ่น stable คือ squeeze (6.0) บนสถาปัตยกรรม amd64 คงไม่มีใครใช้ 32 bit นะ</li>
<li><a href="http://httpd.apache.org/">Apache httpd</a> โดยใช้ MPM แบบ worker แม้ว่าจะมีคู่แข่งอย่าง <a href="http://lighttpd.net/">lighttpd</a> หรือ <a href="http://nginx.net/">nginx</a> แต่ apache httpd มีฟีเจอร์มากมายและตั้งค่าได้ง่าย ในเรื่องความเร็วในการให้บริการเว็บแบบ dynamic content ด้วย PHP ไม่ได้ต่างกันมาก</li>
<li><a href="http://www.mysql.com/">MySQL</a> จริงๆ คือ database server สักตัว แต่ส่วนใหญ่ developer ยังถนัดจะใช้ mysql กันอยู่ ก็ตามนั้นไปก่อน ทางเลือกอื่นๆ ก็มี <a href="http://www.percona.com/">percona</a> ซึ่งเป็น mysql clone, <a href="http://www.postgresql.org/">postgreSQL</a> หรือจะ NoSQL ก็ <a href="http://www.mongodb.org/">mongodb</a>, <a href="http://couchdb.apache.org/">couchdb</a> เป็นต้น</li>
<li><a href="http://php.net/">PHP</a> ตอนนี้ใช้รุ่น 5.3 อยู่ แต่รันแบบ fpm (php5-fpm) ตัวนี้ยังไม่มีบน squeeze แต่สามารถลงได้จาก repo ของ <a href="http://dotdeb.org/">dotdeb.org</a> เป็นตัวที่
รัน php5 ในโหมด fastcgi ซึ่งมีระบบบริหารจัดการโพรเซสด้วย ต่างจาก
php5-cgi ที่แม้ว่าจะรันเป็น fastcgi ได้แต่ชอบมีปัญหา process ค้าง<br />
</li>
</ol>
<h3>
Extensions ส่วนขยายที่ทำให้ระบบทำงานได้ดีขึ้น</h3>
<ol>
<li><a href="http://varnish-cache.org/">varnish</a> ตัวนี้เป็น reverse proxy สำหรับรับ connection ที่ port 80 ก่อนจะส่งต่อให้ apache จุดเด่นคือ ทำ caching ได้, มี apache เป็น backend หลายๆ เครื่องได้ คือทำ load balance ได้นั่นเอง, เขียน script เพื่อจัดการกับภาระกิจบางอย่างได้ เช่น backend เรียกไปแล้ว error 503 กลับมา ก็สั่งให้เรียกไปใหม่ หรือให้แสดงหน้ารอ แล้ว refresh ใหม่ เป็นต้น (503 มักเกิดจาก backend ไม่พร้อมให้บริการในขณะนั้น ส่วนใหญ่รอสักพักแล้ว refresh ก็ใช้ได้ตามปกติ) ปัญหาหนึ่งของการใช้ varnish + apache คือข้อมูลล็อกของ apache จะเก็บ client IP เป็น IP ของ varnish เอง ไม่ใช่ของ client ที่แท้จริง แก้โดยใช้ libapache2-mod-rpaf</li>
<li><a href="http://www.couchbase.com/">couchbase</a> ใช้ทำหน้าที่เป็น memcache โดยใช้สำหรับ 1. เก็บ php session data 2. ใช้เป็น memcache สำหรับเก็บข้อมูล cache ชั่วคราว โดยไม่ต้อง query จาก database บ่อยๆ (ต้องเขียนแอปให้รองรับการใช้ memcache ด้วย) เดิมใช้ <a href="http://memcached.org/">memcached</a> แต่ couchbase ดีกว่าตรงที่ สามารถทำงานแบบ cluster คือมีหลายๆ เครื่องช่วยกันทำงานได้ สามารถเก็บลงดิสก์ได้ มีหน้าเว็บสำหรับ monitor และตั้งค่าต่างๆ ได้</li>
<li><a href="https://launchpad.net/ufw">ufw</a> การกำหนดค่า firewall ด้วย iptables (netfilter) นั้นสำหรับผมเองถือว่ายุ่งยากมาก โดยเฉพาะเวลาที่ต้องกลับมาแก้หรือปรับบางค่าใหม่ พอมาลอง ufw แล้วสะดวกสบายขึ้นมาก</li>
</ol>
<h3>
Luxuries ไม่ได้ทำให้ระบบทำงานดีขึ้น แต่ช่วยสนับสนุนในการติดตามเฝ้าดูระบบ</h3>
<ol>
<li><a href="http://munin-monitoring.org/">munin</a> เอาไว้เก็บข้อมูลการทำงานของระบบไว้ตรวจสอบ โดยมันจะสร้างเป็นชุดของแผนภูมิให้ดูง่ายๆ และสวยงามเลยทีเดียว สามารถใช้เก็บข้อมูลจากหลายๆ เครื่องได้โดยติดตั้งเฉพาะแพกเกจชื่อ munin-node แล้วให้ munin ตัวหลักไปเรียกเอาข้อมูลมาประมวลเป็นแผนภูมิ</li>
<li><a href="http://mmonit.com/monit/">monit</a> เอาไว้คอย monitor ระบบและจัดการแจ้งเตือน หรือรันคำสั่งที่ตั้งไว้ เมื่อตรวจพบเหตุบางอย่าง เช่นเปิดหน้าเว็บที่กำหนดไว้ไม่ได้ ดิสก์เหลือน้อย พบแพทเทิร์นล็อกที่กำหนดไว้ เป็นต้น</li>
<li><a href="http://www.webalizer.org/">webalizer</a> เอาไว้วิเคราะห์ล็อกของ web server แสดงเป็นรูปแผนภูมิสวยงาม ดูง่าย และน่าจะคุ้นเคยกันดี</li>
</ol>kamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com1tag:blogger.com,1999:blog-6885844.post-55225472737614350162012-06-07T12:11:00.003+07:002012-06-07T13:52:11.621+07:00การเซ็ต IPv6 แบบ 6to4 ให้ server<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhYZ2LzN24w-gpopCexgb_g4H1V16Pg03vsr64_jnIb9pdUAuT-05-lmqBIuIMDmGd2oIKePRro6VMmV0wA8N1dFaKJbXHjh0umUle-AKrMRV3DwO-d6eQ94avM3Qvu8-ypp6jkA/s1600/World_IPv6_launch_badge_256.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhYZ2LzN24w-gpopCexgb_g4H1V16Pg03vsr64_jnIb9pdUAuT-05-lmqBIuIMDmGd2oIKePRro6VMmV0wA8N1dFaKJbXHjh0umUle-AKrMRV3DwO-d6eQ94avM3Qvu8-ypp6jkA/s1600/World_IPv6_launch_badge_256.png" /></a></div>
รับกระแส World IPv6 Launch Day ที่เพิ่งมีไปเมื่อวาน (6/6/2012) ซึ่งแปลว่าต่อจากนี้จะเริ่มมีการให้บริการ IPv6 ขนานไปกับ IPv4 มากขึ้น ผู้ที่ต้องตื่นตัวก่อนคือผู้ให้บริการต่างๆ บน Internet นั่นเอง ที่ต้องเตรียมพร้อมรับมือกับมัน (อย่างน้อยก็แสดงให้เห็นว่าเราไม่ตกยุค) ส่วนรายละเอียดว่าทำไมเราต้องเปลี่ยนจาก IPv4 มาเป็น IPv6 ขอให้อ่านจาก <a href="http://www.blognone.com/topics/ipv6">http://www.blognone.com/topics/ipv6</a> นะครับ ในที่นี้ขอพูดถึงประเด็นเดียวคือ เมื่อเรามี server ที่ให้บริการบนเครือข่าย IPv4 อยู่ จะทำอย่างไรให้สามารถบริการ IPv6 ได้<br />
ถ้าเป็นก่อนนี้จะวุ่นวายน่าดูเพราะต้องทำ tunnel ไปยัง IPv6 broker ต่างๆ แต่ตอนนี้มีเทคนิคที่เรียกว่า 6to4 โดยให้ IPv6 encapsulate ไปกับ IPv4 เลย โดยใช้ protocol 41 ซึ่งการตั้งค่าจะเป็นแบบอัตโนมัติ คือไม่ต้องไปหา tunnel ให้วุ่นวาย โดยเมื่อเรามี IPv4 แล้ว เราจะได้รับการจอง subnet ของ IPv6 ไว้ช่วงหนึ่งโดยอัตโนมัติ <br />
<h3>
สิ่งที่ต้องเตรียม</h3>
<ul>
<li>server ที่มี IP จริง (global IP) IP แบบ private ใช้ไม่ได้ อ่อ dynamic IP ก็ไม่ได้นะครับ</li>
<li>โปรแกรม ipv6calc (ติดตั้งบน debian ได้โดยสั่ง apt-get install ipv6calc)</li>
</ul>
<h3>
วิธีการ</h3>
<ul>
<li>แปลงที่อยู่ IPv4 เป็น IPv6 ด้วย ipv6calc โดยสมมติว่า IPv4 คือ 202.183.164.17<br /><pre style="font-family: "Courier New",Courier,monospace;"># ipv6calc --quiet --action conv6to4 202.183.164.17</pre>
<pre style="font-family: "Courier New",Courier,monospace;">2002:cab7:a411::</pre>
</li>
<li>แก้ไขไฟล์ /etc/network/interfaces โดยเพิ่มเนื้อหาตามนี้เข้าไป<br /><pre style="font-family: "Courier New",Courier,monospace;">auto tun6to4
<span class="anchor" id="line-2-2"></span>iface tun6to4 inet6 v4tunnel
<span class="anchor" id="line-3"></span> address <span style="color: #660000;">2002:cab7:a411::1</span>
<span class="anchor" id="line-4"></span> netmask 16
<span class="anchor" id="line-5"></span> gateway ::192.88.99.1
<span class="anchor" id="line-6"></span> endpoint any
<span class="anchor" id="line-7"></span> local <span style="color: #660000;">202.183.164.17</span></pre>
ตรง 2002:cab7:a411::1 มาจาก ipv6calc โดยเพิ่มเลข 1 ต่อท้ายเข้าไป ส่วน local 202.183.164.17 ก็คือ IPv4 ปกติของ server เรา และ gateway ::192.88.99.1 ไม่ต้องแก้นะครับ จะเป็น anycast address สำหรับรับส่ง packet กับ 6to4 relay router ที่ใกล้ที่สุดซึ่งจะมีกระจายอยู่ทั่วโลก</li>
<li>เริ่มใช้งานโดยสั่ง<br /><span style="font-family: "Courier New",Courier,monospace;"># ifup tun6to4</span></li>
<li>ทดสอบโดยสั่ง<br /><span style="font-family: "Courier New",Courier,monospace;"># ping6 google.com</span></li>
<li>ถ้าใช้ไม่ได้อาจจะเกิดจาก firewall ในเครื่องเราเองที่ปกติจะไม่รับ protocol 41 ให้แก้โดยสั่ง<br /><span style="font-family: "Courier New",Courier,monospace;"># iptables -I INPUT -p 41 -j ACCEPT</span><br /><span style="font-family: "Courier New",Courier,monospace;"># iptables -I OUTPUT -p 41 -j ACCEPT</span><br />แล้วลองทดสอบใหม่ ถ้าใช้ได้ก็เอาไปเพิ่มใน firewall script ของเรา เช่นผมใช้ ufw ก็เพิ่ม -I INPUT -p 41 -j ACCEPT และ -I OUTPUT -p 41 -j ACCEPT ไว้ที่ /etc/ufw/before.rules ก่อนหน้าบรรทัด COMMIT</li>
<li>แต่ถ้าใช้ไม่ได้เพราะ firewall ของ NOC ไม่ forward protocol 41 มาให้ ก็ต้องคุยกับผู้ให้บริการให้เปิดรับ protocol 41 ด้วย ปกติไม่เคยเจอปัญหานี้ที่ผู้ให้บริการทั่วไป แต่ถ้าภายในองค์กรอาจจะมีปัญหานี้ได้</li>
<li>ทดสอบการใช้บริการต่างๆ ผ่าน IPv6 ในที่นี้เราต้องใช้ IPv6 จากเครื่อง client ได้ก่อน<br />เช่น เปิด browser ไปยัง url http://[2002:cab7:a411::1] หรือ ssh 2002:cab7:a411::1</li>
<li>ตรวจสอบบริการต่างๆ ให้รองรับ IPv6 ตรวจสอบการตั้งค่า firewall ให้รองรับ IPv6</li>
<li>ถ้ามั่นใจแล้วก็เพิ่ม record AAAA 2002:cab7:a411::1 ไปที่ DNS ของเราได้เลย เพื่อให้ผู้ใช้ที่ใช้ IPv6 ได้ สามารถติดต่อกับ site ของเราผ่าน IPv6 ได้โดยตรง</li>
</ul>
ดูเพิ่มเติม : <a href="http://wiki.debian.org/DebianIPv6">http://wiki.debian.org/DebianIPv6</a>kamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com0ศูนย์เทคโนโลยีอิเล็กทรอนิกส์และคอมพิวเตอร์แห่งชาติ14.077889943841257 100.6017208099365214.070188943841256 100.59185030993652 14.085590943841257 100.61159130993653tag:blogger.com,1999:blog-6885844.post-67169329725974968992011-09-13T12:17:00.000+07:002011-09-13T12:18:01.459+07:00MySQL Query Optimization 2 : เครื่องมือช่วยเป็นแบบนี้ไหมครับ รู้ว่าปัญหาอยู่ที่ MySQL นี่แหละ แต่เป็นตรงไหนล่ะ เรามาดูเครื่องมือช่วยกันดีกว่า<br />
<br />
<b>mysqltuner</b><br />
ตัวนี้สำหรับ admin โดยมันจะวิเคราะห์ข้อมูลต่างๆ ของ MySQL server ในขณะนั้นแล้วแนะนำว่าควรปรับค่าอะไร อย่างไร อันเนื่องมาจากว่าไม่มีสูตรตายตัวว่าควรปรับแต่งอย่างไร ซึ่งขึ้นอยู่กับข้อมูล และการใช้งานจริงด้วย<br />
<br />
การติดตั้ง<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># wget <a href="http://mysqltuner.pl/">mysqltuner.pl</a> -O mysqltuner.pl</span><br />
<br />
เป็นการติดตั้งที่เท่มาก คือตัวนี้เป็น perl script ซึ่งปกติมันจะใช้ extension เป็น .pl เค้าเลยไปจดชื่อ domain เป็น mysqltuner.pl ไว้ คำสั่งนี้จึงหมายถึง ดาวน์โหลดหน้าเว็บหลักของ <a href="http://mysqltuner.pl/">http://mysqltuner.pl/</a> ซึ่งมันจะให้ข้อมูลเป็น script รุ่นล่าสุดเสมอ เอามาบันทึกไว้ในชื่อ mysqltuner.pl<br />
<br />
จากนั้นกำหนดให้ execute ได้<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># chmod +x mysqltuner.pl</span><br />
<br />
การใช้ สั่ง ./mysqltuner.pl แล้วใส่ชื่อแอดมินของ MySQL ปกติคือ root และรหัสผ่าน ก็จะได้ผลลัพธ์คล้ายๆ แบบนี้<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace; font-size: x-small;"># ./mysqltuner.pl</span><br />
<span class="Apple-style-span" style="color: #274e13;"><br /></span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"> >> MySQLTuner 1.2.0 - Major Hayden <major@mhtx.net></span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"> >> Bug reports, feature requests, and downloads at http://mysqltuner.com/</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"> >> Run with '--help' for additional options and output filtering</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">Please enter your MySQL administrative login: <b>root</b></span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">Please enter your MySQL administrative password: </span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">-------- General Statistics --------------------------------------------------</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[--] Skipped version check for MySQLTuner script</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[OK] Currently running supported MySQL version 5.1.58-1~dotdeb.1-log</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[OK] Operating on 64-bit architecture</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">-------- Storage Engine Statistics -------------------------------------------</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[--] Status: +Archive -BDB -Federated -InnoDB -ISAM -NDBCluster </span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[--] Data in MyISAM tables: 30G (Tables: 670)</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[--] Data in MEMORY tables: 45M (Tables: 8)</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[!!] Total fragmented tables: 130</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">-------- Security Recommendations -------------------------------------------</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[OK] All database users have passwords assigned</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">-------- Performance Metrics -------------------------------------------------</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[--] Up for: 3d 7h 10m 37s (43M q [153.856 qps], 1M conn, TX: 20B, RX: 8B)</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[--] Reads / Writes: 49% / 51%</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[--] Total buffers: 1.6G global + 8.4M per thread (500 max threads)</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[OK] Maximum possible memory usage: 5.7G (73% of installed RAM)</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[OK] Slow queries: 3% (1M/43M)</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[OK] Highest usage of available connections: 36% (180/500)</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[OK] Key buffer size / total MyISAM indexes: 1000.0M/19.4G</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[OK] Key buffer hit rate: 99.9% (2B cached / 4M reads)</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[!!] Query cache efficiency: 19.2% (3M cached / 17M selects)</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[OK] Query cache prunes per day: 0</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[OK] Sorts requiring temporary tables: 0% (162 temp sorts / 1M sorts)</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[OK] Temporary tables created on disk: 0% (52 on disk / 734K total)</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[OK] Thread cache hit rate: 64% (686K created / 1M connections)</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[!!] Table cache hit rate: 19% (1K open / 9K opened)</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[OK] Open file limit used: 55% (16K/30K)</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">[OK] Table locks acquired immediately: 97% (224M immediate / 231M locks)</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">-------- Recommendations -----------------------------------------------------</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">General recommendations:</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"> Run OPTIMIZE TABLE to defragment tables for better performance</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"> Increase table_cache gradually to avoid file descriptor limits</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">Variables to adjust:</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"> query_cache_limit (> 16M, or use smaller result sets)</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"> table_cache (> 1800)</span><br />
<br />
ผลลัพธ์ก็อธิบายในตัวเองค่อนข้างชัดเจน บรรทัดที่นำหน้าด้วย [OK] ก็คือดีแล้ว ไม่มีปัญหาอะไร นำหน้าด้วย [--] คือเป็นข้อมูลแจ้งให้ทราบ ส่วน [!!] อันนี้ไม่ดีละ มีบางอย่างควรต้องพิจารณา ซึ่งจะมีสรุปด้านล่างว่าควรทำอะไร หรือปรับค่าตัวแปรอะไร เพื่อให้ประสิทธิภาพดีขึ้น แต่ไม่ต้องเชื่อมันทุกอย่างก็ได้ ฟังไว้เป็นข้อมูลประกอบก็พอ<br />
<br />
ดูเพิ่มเติม <a href="http://mysqltuner.com/">http://mysqltuner.com/</a><br />
<br />
<b>mysql_slow_log_parser</b><br />
ตัวนี้เหมาะสำหรับ developer ไว้วิเคราะห์ว่า query ใดเป็นตัวปัญหา โดยปกติเราสามารถกำหนดให้ MySQL บันทึก log ของ slow query ที่เกิดขึ้น แต่ปัญหาคือมันเยอะมากจนไม่รู้จะเริ่มดูตรงไหนก่อน ตัวนี้จะช่วยเอา slow log ทั้งหมดมารวบรวม จัดหมวดหมู่คำสั่งที่คล้ายกัน นำจำนวน รวมเวลาที่ใช้ทั้งหมด เวลาน้อยสุด เวลามากสุด เวลาเฉลี่ย แล้วเรียงลำดับตามเวลา query ทั้งหมดที่ใช้ไปจากมากไปน้อย<br />
<br />
การติดตั้ง<br />
ก่อนอื่นให้ตั้งค่าของ MySQL server ให้เก็บ slow log query ก่อน โดยแก้ไฟล์ /etc/mysql/my.cnf แล้ว uncomment และแก้บรรทัด 2 บรรทัดนี้<br />
<br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">log_slow_queries = /var/log/mysql/mysql-slow.log</span><br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">long_query_time = 0</span><br />
<div>
<br /></div>
<div>
สังเกตว่าเราจะกำหนด long_query_time เป็น 0 นั่นคือให้เก็บ log ทุก query ไว้หมด เพื่อนำมาวิเคราะห์ จากนั้น restart mysql ด้วยคำสั่ง</div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># /etc/init.d/mysql restart</span></div>
<div>
<br /></div>
<div>
ดาวน์โหลด script mysql_slow_log_parser</div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># wget <a href="http://www.mysqlperformanceblog.com/files/utils/mysql_slow_log_parser">http://www.mysqlperformanceblog.com/files/utils/mysql_slow_log_parser</a></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># chmod +x mysql_slow_log_parser</span></div>
<div>
<br /></div>
<div>
การใช้งาน</div>
<div>
ถ้าเป็นล็อกที่เกิดในวันนี้ คือหลังจากที่ logrotate ทำงาน ให้สั่ง</div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># ./mysql_slow_log_parser /var/log/mysql/mysql-slow.log > mysql-slow-info.txt</span></div>
<div>
<br /></div>
<div>
ดูผลที่เก็บในไฟล์</div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># less mysql-slow-info.txt</span></div>
<div>
<br /></div>
<div>
ถ้าเป็นล็อกที่เกิดขึ้นในวันก่อนๆ ซึ่งถูก rotate และ compress ไปแล้ว</div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># zcat /var/log/mysql/mysql-slow.log.1.gz | ./mysql_slow_log_parser > mysql-slow-info.1.txt</span></div>
<div>
<br /></div>
<div>
ดูผลที่เก็บในไฟล์</div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># less mysql-slow-info.1.txt</span></div>
<div>
<br /></div>
<div>
ตัวอย่างไฟล์ mysql-slow.log</div>
<div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"># User@Host: xxx[xxx] @ localhost [127.0.0.1]</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"># Query_time: 0.004879 Lock_time: 0.000031 Rows_sent: 1 Rows_examined: 2313</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">SET timestamp=1315178855;</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">SELECT COUNT(*) AS numRows FROM group_topics WHERE group_id=167 AND status='NORMAL';</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"># Time: 110905 6:27:37</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"># User@Host: xxx[xxx] @ localhost [127.0.0.1]</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"># Query_time: 0.182972 Lock_time: 0.000036 Rows_sent: 1 Rows_examined: 104030</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">SET timestamp=1315178857;</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">SELECT member_id FROM member WHERE LOWER(user_id)='xxxxx' AND is_active='1' LIMIT 1;</span></div>
</div>
<div>
<br /></div>
<div>
ตัวอย่างผลลัพธ์ หลังจากผ่าน parser</div>
<div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"> Starting... </span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">### 53018 Queries </span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">### Total time: 204742.585691, Average time: 3.86175611473462</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">### Taking 0.000740 to 81.100860 seconds to complete</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">### Rows analyzed 100 - 1467</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">SET timestamp=XXX;</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">SELECT COUNT(*) AS total FROM chat_msgs WHERE owner_id=XXX AND is_unread='XXX';</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">SET timestamp=1315178847;</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">SELECT COUNT(*) AS total FROM chat_msgs WHERE owner_id=104170 AND is_unread='1';</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">### 29081 Queries </span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">### Total time: 90838.2220840001, Average time: 3.12362786988068</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">### Taking 0.000353 to 82.103217 seconds to complete</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">### Rows analyzed 100 - 4387</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">SET timestamp=XXX;</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">SELECT friend_id FROM relation WHERE member_id=XXX AND status='XXX';</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">SET timestamp=1315178835;</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: x-small;">SELECT friend_id FROM relation WHERE member_id=235929 AND status='ACCEPT';</span></div>
<div>
<br /></div>
</div>
<div>
สังเกตว่ามันจะแปลงส่วน value ทั้ง string และตัวเลข ให้เป็น XXX ก่อน แล้วนำมาแยกนับ วิเคราะห์คำสั่งที่เหมือนกัน ก็จะทำให้ทราบว่าคำสั่งใดถูกใช้บ่อยแค่ไหน (กี่ query) ใช้เวลารวมทั้งหมดเท่าไหร่ (Total time:) ใช้เวลาเฉลี่ยต่อ query เท่าไหร่ (Average time:) ใช้เวลาน้อยสุดถึงมากสุดเท่าไหร่ (Taking ... to ... seconds to complete) จำนวน rows ของผลลัพธ์ โดยมันจะแสดง query ที่ใช้เวลารวมมากที่สุดก่อน ซึ่งถ้า optimize ได้ก็จะมีผลมากที่สุด</div>
<br />
อ่อ ที่เห็นผลลัพธ์อันนี้ดูแย่ๆ คือ average สูง และช่วงเวลาที่ใช้ต่ำสุด - สูงสุดกว้างขนาดนี้ เพราะมีปัญหาเรื่อง capacity ของเครื่องไม่พอน่ะครับ จึงเร็วบ้าง ช้าบ้าง ไม่แน่ไม่นอนkamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com0tag:blogger.com,1999:blog-6885844.post-18231906281235374652011-09-04T18:59:00.000+07:002011-09-04T18:59:00.115+07:00MySQL Query Optimization 1<span class="Apple-style-span" style="background-color: white; line-height: 16px;"></span><br />
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
มีเหตุให้ต้องได้ช่วยฝ่ายอื่นแก้ปัญหาเรื่องประสิทธิภาพของเซิร์ฟเวอร์ลินุกซ์เลยขอบันทึกไว้หน่อยว่าเจออะไรบ้าง</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
<br /></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
เซิร์ฟเวอร์ให้บริการเว็บ ใช้ apache + php5 + mysql ตามปกติ อาการแรกที่เห็นคือเซิร์ฟเวอร์ไม่ตอบสนอง ถึงขนาด ssh เข้าไปยังต้องรอนานมาก และ timeout ไปหลายรอบกว่าจะเข้าได้ อาการนี้มักเกิดจากหน่วยความจำเต็ม จนต้อง swap หน่วยความจำบางส่วนลงดิสก์ ซึ่งบังเอิญหน่วยความจำที่มัน active อยู่ มันเกินหน่วยความจำจริง เลยเกิดการ swap ตลอดเวลา จน process ต่างๆ แทบจะทำงานอะไรไม่ได้ เพราะต้องรอหน่วยความจำจากดิสก์ก่อน</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
<br /></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
ทำไมหน่วยความจำจึงไม่พอ</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
เซิร์ฟเวอร์ตัวนี้ มีหน่วยความจำ 3GB ไม่ได้มากนัก แต่ก็ไม่น้อยเกินไป สาเหตุที่หน่วยความจำเต็มเกิดจาก apache httpd เกิดการแบ่งตัวเพื่อรับภาระงานจนเกินขนาดของหน่วยความจำ ซึ่งปกติเวลามี connection เข้ามา 1 อัน ต้องใช้ httpd 1 process ในการรับงาน แต่ละ process มีขนาดประมาณ 9-12MB กำหนดไว้สูงสุด 250 client ซึ่งเช็คแล้วพบว่าเต็ม 250 เลย จับคูณกันแล้วก็ราวๆ 3GB พอดี ยังไม่รวม mysql และอื่นๆ</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
การเพิ่มหน่วยความจำไม่ใช่ทางออกที่ถูกต้อง จริงๆ หน่วยความจำเยอะๆ ดี แต่มันจะไม่ช่วยในกรณีนี้ เพราะเทียบได้กับการให้บริการอะไรสักอย่างของหน่วยงานหนึ่ง แล้วพบว่าที่นั่งรอไม่พอ เลยขยายห้องรอเป็นสองเท่า เพื่อให้คนเข้ามารอได้เป็นสองเท่า จริงๆ ต้องไปแก้ที่ต้นเหตุคือทำไมการให้บริการของหน่วยงานนั้นๆ ถึงได้ช้า</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
<br /></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
ทำไม apache httpd ถึงช้าจนเกิด connection ค้างมากถึง 250 อัน</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
ส่วนใหญ่ (รวมทั้งกรณีนี้ด้วย) คือเกิดสภาวะรอ mysql ตอบ query ที่เรียกไป</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
<br /></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
แล้วทำไม mysql มันช้านัก</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
ในหลายกรณี (รวมทั้งกรณีนี้ด้วย) คือการเรียกใช้ query ไม่ได้ถูก optimize ให้ทำงานได้ดีที่สุด</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
<br /></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
การตรวจสอบว่า query ใดทำให้ mysql ช้า</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
ให้เปิดใช้ฟีเจอร์เก็บล็อกของ query ที่ช้าโดยเพิ่ม</div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">log_slow_queries = /var/log/mysql-slow.log</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">long_query_time = 5</span></div>
<div style="color: #333333; line-height: 1.5em;">
เข้าไปใน section [mysqld] ในไฟล์ my.cnf ซึ่งน่าจะอยู่ใน /etc/mysql หรือ /etc</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
แล้ว restart mysql แล้วตามเฝ้าดูในไฟล์ /var/log/mysql-slow.log</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
<br /></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
หลักการ optimize query</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
อันแรกสุดคือลดการเกิด full table scan ให้มากที่สุด full table scan คือการที่จะหาคำตอบของ query จำเป็นต้อง scan อ่านทั้งตาราง ซึ่งจะช้ามาก และช้าขึ้นเรื่อยๆ เมื่อตารางใหญ่ขึ้น การลดอาการนี้อันแรกคือ ให้ทำ index ที่จำเป็นต้องใช้บ่อยๆ เสมอ โดยให้ดูที่ ORDER BY กับ WHERE ว่ามีการอ้างถึง column ใดบ้าง อีกอันที่เจอคือบางคนใช้ WHERE sss LIKE '%xxxx%' ในการเปรียบเทียบ string ทั้งๆ ที่ xxxx นั่นคือทั้งหมดที่อยู่ใน column นั้นๆ อยู่แล้ว การใช้ %xxxx% ทำให้เกิดการค้นหาตลอดตารางเพื่อหาทุกแถวที่เป็นไปได้ ที่จริงแล้วในกรณีนี้ใช้แค่ WHERE sss = 'xxxx' ก็ได้</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
อีกอันคือให้หลีกเลี่ยงการ JOIN ให้มากที่สุด อาจจะลองเลี่ยงไปใช้ sub query ก็ช่วยได้พอสมควร</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
<br /></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
ตัวอย่างการ optimize query</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
<br /></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
ของเดิม</div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">SELECT topic.ID, topic.Title, topic.Description, topic.Publisher_Name, topic.Upload_Date</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">FROM topic</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> LEFT JOIN topic_category ON ( topic.ID = topic_category.Topic_ID)</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> LEFT JOIN topic_media ON (topic.ID = topic_media.Topic_ID)</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">WHERE</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> topic.Status = 1</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> AND topic_media.Status = 1</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> AND topic.Approve_State = 1</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> AND topic_media.Type like '%image%'</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">GROUP BY</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> topic.ID</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">ORDER BY</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> topic.ID DESC</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">LIMIT 65625, 25;</span></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
ใช้เวลา 13.20 วินาที</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
<br /></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
เปลี่ยน like '%...%' เป็น = '...'</div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">SELECT topic.ID, topic.Title, topic.Description, topic.Publisher_Name, topic.Upload_Date</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">FROM topic</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> LEFT JOIN topic_category ON ( topic.ID = topic_category.Topic_ID)</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> LEFT JOIN topic_media ON (topic.ID = topic_media.Topic_ID)</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">WHERE</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> topic.Status = 1</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> AND topic_media.Status = 1</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> AND topic.Approve_State = 1</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> AND topic_media.Type = 'image'</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">GROUP BY</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> topic.ID</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">ORDER BY</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> topic.ID DESC</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">LIMIT</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> 65625, 25;</span></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
ใช้เวลา 12.79 วินาที</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
<br /></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
สังเกตว่าใช้ GROUP BY แต่ไม่มีการใช้ aggregate function เช่น sum() หรือ count() แสดงว่าแค่ตั้งใจให้แสดงแถวแบบไม่ซ้ำ ลองเปลี่ยนเป็น DISTINCT</div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">SELECT DISTINCT topic.ID, topic.Title, topic.Description, topic.Publisher_Name, topic.Upload_Date</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">FROM topic</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> LEFT JOIN topic_category ON ( topic.ID = topic_category.Topic_ID)</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> LEFT JOIN topic_media ON (topic.ID = topic_media.Topic_ID)</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">WHERE</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> topic.Status = 1</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> AND topic_media.Status = 1</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> AND topic.Approve_State = 1</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> AND topic_media.Type = 'image'</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">ORDER BY</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> topic.ID DESC</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">LIMIT</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> 65625, 25 ;</span></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
ใช้เวลา 10.65 วินาที</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
<br /></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
สังเกตพบว่ามีการ LEFT JOIN ตาราง topic_category แต่ไม่ได้เอามาใช้ทำอะไร งั้นตัดทิ้งไป</div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">SELECT DISTINCT topic.ID, topic.Title, topic.Description, topic.Publisher_Name, topic.Upload_Date</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">FROM topic LEFT JOIN topic_media ON (topic.ID = topic_media.Topic_ID)</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">WHERE</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> topic.Status = 1</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> AND topic_media.Status = 1</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> AND topic.Approve_State = 1</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> AND topic_media.Type = 'image' </span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">ORDER BY</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> topic.ID DESC</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">LIMIT</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> 65625, 25 ;</span></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
ใช้เวลา 8.98 วินาที</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
<br /></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
เปลี่ยนจากการทำ LEFT JOIN เป็น sub query select</div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">SELECT DISTINCT ID, Title, Description, Publisher_Name, Upload_Date</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">FROM topic</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">WHERE</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> ID IN (SELECT Topic_ID FROM topic_media WHERE Status = 1 AND Type = 'image')</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> AND Status = 1</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> AND Approve_State = 1 </span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">ORDER BY</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> ID DESC</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">LIMIT</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> 65625, 25 ;</span></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
เหลือ 3.43 วินาที</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
<br /></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
ลองใช้ EXPLAIN SELECT เพื่อวิเคราะห์ว่ามีอะไรไม่เป็นไปตามที่ต้องการหรือไม่</div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: xx-small;">EXPLAIN SELECT sql_no_cache DISTINCT ID, Title, Description, Publisher_Name, Upload_Date FROM topic WHERE ID IN (SELECT Topic_ID FROM topic_media WHERE Status = 1 AND Type = 'image') AND Status = 1 AND Approve_State = 1 ORDER BY ID DESC LIMIT 65625, 25 ;</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: xx-small;">+----+--------------------+-------------+----------------+----------------------+---------------+---------+-------+-------+-----------------------------+</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: xx-small;">| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: xx-small;">+----+--------------------+-------------+----------------+----------------------+---------------+---------+-------+-------+-----------------------------+</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: xx-small;">| 1 | PRIMARY | topic | ref | Approve_State,Status | Approve_State | 1 | const | 75581 | Using where; Using filesort |</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: xx-small;">| 2 | DEPENDENT SUBQUERY | topic_media | index_subquery | Topic_ID,Type,Status | Topic_ID | 8 | func | 2 | Using where |</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: xx-small;">+----+--------------------+-------------+----------------+----------------------+---------------+---------+-------+-------+-----------------------------+</span></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
พบว่า มี Using filesort เพราะตอน query นั้น mysql ให้ความสำคัญกับการ look up (WHERE) ก่อน จึงใช้ index Approve_State หรือ Status ส่วน PRIMARY ที่จำเป็นต้องใช้ตอนเรียงลำดับ (ORDER BY) ไม่ได้ใช้ (ขณะ query สามารถเลือก index ได้อันเดียว) ทำให้ต้องเสียเวลาไปเรียงข้อมูลใหม่ก่อน ในกรณีนี้อาจจะลองบังคับให้ใช้ index ที่ต้องการ โดยเพิ่ม FORCE INDEX (keyname) หลังชื่อตาราง เช่น</div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: xx-small;">EXPLAIN SELECT sql_no_cache DISTINCT ID, Title, Description, Publisher_Name, Upload_Date FROM topic FORCE INDEX (PRIMARY) WHERE ID IN (SELECT Topic_ID FROM topic_media WHERE Status = 1 AND Type = 'image') AND Status = 1 AND Approve_State = 1 ORDER BY ID DESC LIMIT 65625, 25 ;</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: xx-small;">+----+--------------------+-------------+----------------+----------------------+----------+---------+------+-------+-------------+</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: xx-small;">| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: xx-small;">+----+--------------------+-------------+----------------+----------------------+----------+---------+------+-------+-------------+</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: xx-small;">| 1 | PRIMARY | topic | index | NULL | PRIMARY | 8 | NULL | 65650 | Using where |</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: xx-small;">| 2 | DEPENDENT SUBQUERY | topic_media | index_subquery | Topic_ID,Type,Status | Topic_ID | 8 | func | 2 | Using where |</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace; font-size: xx-small;">+----+--------------------+-------------+----------------+----------------------+----------+---------+------+-------+-------------+</span></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
เมื่อเอา EXPLAIN ออก รันด้วยคำสั่งจริง </div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">SELECT sql_no_cache DISTINCT ID, Title, Description, Publisher_Name, Upload_Date </span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">FROM topic FORCE INDEX (PRIMARY) </span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">WHERE </span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> ID IN (SELECT Topic_ID FROM topic_media WHERE Status = 1 AND Type = 'image') </span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> AND Status = 1 </span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> AND Approve_State = 1 </span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">ORDER BY </span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> ID DESC </span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">LIMIT</span></div>
<div style="line-height: 1.5em;">
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> 65625, 25 ;</span></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
ใช้เวลา 2.22 วินาที</div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
<br /></div>
<div style="color: #333333; font-family: inherit; line-height: 1.5em;">
ทั้งหมดนี้คือได้ผลลัพธ์เหมือนเดิมเป๊ะ</div>
kamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com1tag:blogger.com,1999:blog-6885844.post-13005667877390244242011-09-01T13:30:00.004+07:002011-09-01T13:30:56.930+07:00MD RAID Migration จาก partition ธรรมดา เป็น RAID1,5,6,10คำเตือน: บทความนี้มีขั้นตอนการสั่งงานระบบที่ค่อนข้างมีความเสี่ยงที่จะทำให้ข้อมูลสูญหายได้ ถ้าใช้งานจริง โปรดสำรองข้อมูลก่อนเสมอ ทุกคำสั่งควรทบทวนอย่างระมัดระวัง และต้องดัดแปลงให้ตรงกับสถานการณ์จริง และควรตรวจสอบผลลัพธ์ว่าเป็นไปตามที่ต้องการหรือไม่ ก่อนจะดำเนินการขั้นต่อไป<br />
<br />
ปกติเรามักจะทำ RAID ก่อนที่จะติดตั้งระบบ โดยเฉพาะเมื่อต้องคอนฟิก hardware RAID นั้น เป็นไปไม่ได้เลยที่จะติดตั้งระบบบนดิสก์ตัวเดียวก่อน แล้วค่อยเปลี่ยนเป็น RAID ภายหลัง<br />
แต่ความยืดหยุ่นของ Linux MD RAID ทำให้การ migrate จากพาร์ทิชันธรรมดา มาเป็น RAID ได้ ซึ่งทำได้เฉพาะกับ RAID ที่รองรับ redundant ดังนั้นจึงใช้กับ RAID0 ไม่ได้<br />
ในขั้นแรก ขอยกตัวอย่างการ migrate จาก พาร์ทิชันธรรมดา -> RAID1<br />
สถานการณ์ เดิมมีฮาร์ดดิสก์ 1 ตัว (sda) แบ่งเป็น<br />
<br />
<ol>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">/boot</span></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">swap</span></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">/</span></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">/var</span></li>
</ol>
<div>
ต่อมาเพิ่มฮาร์ดดิสก์อีกตัวขนาดเท่ากัน (sdb) จะทำ RAID1 ทุกพาร์ทิชัน ยกเว้น swap</div>
<br />
หลักการคือ เราจะทำให้ sdb ทำงานเป็น RAID1 ที่มีสถานะ degraded คือมีดิสก์ไม่ครบ แต่ยังทำงานได้ คือมีดิสก์เพียง 1 ตัว จากที่ต้องการจริงคือ 2 ตัว แล้วย้ายข้อมูลจาก sda แต่ละพาร์ทิชัน ไปยัง RAID1 แต่ละพาร์ทิชันที่สร้างขึ้น ปรับ boot parameter ต่างๆ ให้บูตและเมานท์จาก RAID ทั้งหมด แล้วรีบูต แล้วค่อยเพิ่ม sda แต่ละพาร์ทิชันเข้ามาใน RAID แต่ละชุด<br />
<br />
ขั้นตอน<br />
โคลนโครงสร้างพาร์ทิชัน<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>sfdisk -d /dev/sda | sfdisk -L /dev/sdb</b></span><br />
<br />
เปลี่ยนชนิดของพาร์ทิชันเป็น Linux raid autodetect (fd)<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>fdisk /dev/sdb</b></span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"><b>t</b></span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"><b>1</b></span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"><b>fd</b></span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"><b>t</b></span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"><b>3</b></span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"><b>fd</b></span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"><b>t</b></span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"><b>4</b></span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"><b>fd</b></span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"><b>w</b></span><br />
<br />
สร้าง swap<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mkswap /dev/sdb2</b></span><br />
<br />
ติดตั้ง mdadm<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>apt-get install mdadm</b></span><br />
<br />
สร้าง RAID1 ในพาร์ทิชัน 1,3,4<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mdadm --create /dev/md0 --level=1 --raid-devices=2 --metadata=0.9 missing /dev/sdb1</b></span><br />
<br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mdadm --create /dev/md1 --level=1 --raid-devices=2 missing /dev/sdb3</b></span></div>
<div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mdadm --create /dev/md2 --level=1 --raid-devices=2 missing /dev/sdb4</b></span></div>
</div>
<div>
สำหรับ raid ชุดแรกที่จะให้บูตได้ ควรกำหนดให้ใช้ metadata version 0.9 ส่วนตัวอื่นๆ ไม่ระบุ มันจะใช้ metadata version 1.2 และจะระบุ device เป็น missing เพื่อเว้นไว้เพิ่ม sda เข้ามาภายหลัง</div>
<div>
<br /></div>
<div>
จากนั้นสร้าง filesystem</div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mkfs.ext2 -L boot -m 0 /dev/md0</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mkfs.ext4 -L root /dev/md1</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mkfs.ext4 -L var /dev/md2</b></span></div>
<div>
<br /></div>
<div>
เมานท์และคัดลอกไฟล์ จากพาร์ทิชันเดิม ในขั้นตอนนี้ ถ้ามีโปรแกรม หรือ service อะไรรันไว้ แ้ล้วอาจจะมีการเปิดไฟล์ค้างไว้ ควรหยุดโปรแกรมหรือ service นั้นก่อน เช่น MySQL มิฉะนั้นแล้วข้อมูลที่คัดลอกไปจะไม่สมบูรณ์ ถ้าไม่แน่ใจ ให้ reboot ระบบเป็น single user mode ก่อน</div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mkdir /mnt/root</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mount /dev/md1 /mnt/root</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mkdir /mnt/old-root</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mount -o bind / /mnt/old-root</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>(cd /mnt/old-root ; tar c . ) | (cd /mnt/root ; tar xpv )</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>umount /mnt/old-root</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>rmdir /mnt/old-root</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>rmdir /mnt/root/mnt/old-roo</b>t</span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>rmdir /mnt/root/mnt/root</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mount /dev/md0 /mnt/root/boot</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>(cd /boot ; tar c . ) | (cd /mnt/root/boot ; tar xpv )</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mount /dev/md2 /mnt/root/var</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>(cd /var ; tar c . ) | (cd /mnt/root/var ; tar xpv )</b></span></div>
<div>
<br /></div>
<div>
ต่อไปจะ chroot และติดตั้ง boot loader ใหม่ และแก้ไขค่าเกี่ยวกับการบูตทั้งหมด</div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mount -o bind /dev /mnt/root/dev</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mount -t proc none /mnt/root/proc</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mount -t devpts none /mnt/root/dev/pts</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mount -t sysfs none /mnt/root/sys</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>chroot /mnt/root /bin/bash --login</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>vi /etc/fstab</b></span></div>
<div>
(หรือ nano /etc/fstab แล้วแต่ถนัด editor ใด)</div>
<div>
แล้้วแก้ไขพาร์ทิชัน หรือ UUID เดิมให้เป็น /dev/md0 สำหรับ /boot, /dev/md1 สำหรับ / และ /dev/md2 สำหรับ /var และเพิ่ม swap ให้กับ /dev/sdb2</div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mdadm --examine --scan >> /etc/mdadm/mdadm.conf</b></span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>update-grub</b></span><br />
<br />
</div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>grub-install /dev/sda</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>grub-install /dev/sdb</b></span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>update-initramfs -u</b></span></div>
<div>
<br /></div>
<div>
ตรวจดูในไฟล์ /boot/grub/grub.cfg ว่า ในบรรทัดที่ขึ้นต้นด้วย linux ได้กำหนด root=/dev/md1 ถูกต้องหรือไม่ โดยปกติจะถูกกำหนดไว้ถูกต้องแล้วด้วยโปรแกรม update-grub</div>
<div>
จากนั้นสั่ง reboot<br />
<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;">#<b> exit</b></span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;">#<b> umount /mnt/root/sys</b></span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;">#<b> umount /mnt/root/dev/pts</b></span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;">#<b> umount /mnt/root/proc</b></span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;">#<b> umount /mnt/root/dev</b></span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;">#<b> umount /mnt/root</b></span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;">#<b> reboot</b></span></div>
<div>
<br /></div>
<div>
เมื่อบูตแล้วระบบควรจะใช้ /dev/md1 เป็น root ลองตรวจสอบด้วยคำสั่ง mount</div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mount</b></span></div>
<div>
<div>
ควรจะพบบรรทัดนี้</div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">/dev/md1 on / type ext4 (rw,noatime)</span></div>
</div>
<div>
<br /></div>
<div>
เมื่อสั่ง</div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>cat /proc/mdstat</b></span></div>
<div>
จะพบระบบ RAID ยังเป็น degraded อยู่ ดังนี้</div>
<div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">md0 : active raid1 sdb1[1]</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> 262140 blocks [2/1] [_U]</span></div>
</div>
<div>
<div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">md1 : active raid1 sdb3[1]</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> 5242816 blocks [2/1] [_U]</span></div>
</div>
</div>
<div>
<div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">md2 : active raid1 sdb4[1]</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> 41942480 blocks [2/1] [_U]</span></div>
</div>
</div>
<div>
<br /></div>
<div>
ตรวจสอบระบบและข้อมูลต่างๆ ว่ายังปกติดี เมื่อมั่นใจแล้วก็เอาพาร์ทิชันต่างๆ ใน sda มารวมเข้ากับระบบ RAID</div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>fdisk /dev/sda</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"><b>t</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"><b>1</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"><b>fd</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"><b>t</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"><b>3</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"><b>fd</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"><b>t</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"><b>4</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"><b>fd</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"><b>w</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mdadm /dev/md0 --add /dev/sda1</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mdadm /dev/md1 --add /dev/sda3</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mdadm /dev/md2 --add /dev/sda4</b></span></div>
<div>
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>cat /proc/mdstat</b></span></div>
<div>
<div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">md0 : active raid1 sdb1[1]</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> 262140 blocks [2/1] [_U]</span></div>
</div>
<div>
<div>
<div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> [============>........] recovery = 63.5% (166458/262140) finish=0.4min speed=3504K/sec</span></div>
</div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">md1 : active raid1 sdb3[1]</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> 5242816 blocks [2/1] [_U]</span></div>
</div>
</div>
<div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>resync=DELAYED</span></div>
</div>
<div>
<div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">md2 : active raid1 sdb4[1]</span></div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> 41942480 blocks [2/1] [_U]</span></div>
</div>
</div>
<div>
<div>
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> <span class="Apple-tab-span" style="white-space: pre;"> </span>resync=DELAYED</span></div>
</div>
</div>
<div>
<br /></div>
<div>
RAID จะ resync จาก sdb ไปยัง sda ซึ่งระยะเวลาขึ้นอยู่กับขนาดของพาร์ทิชันและความเร็วในการอ่านเขียนดิสก์ รวมถึงความ busy ของดิสก์ด้วย</div>
<div>
ในระหว่างนี้ ถ้าเป็น server เราก็สามารถให้บริการได้ตามปกติ แต่ก็จะทำให้การ sync ข้อมูลของ RAID ช้าไปด้วย</div>
<div>
<br /></div>
<div>
ถ้าจะ migrate จากพาร์ทิชันธรรมดา ไปเป็น RAID5,6 หรือ RAID10 ก็ทำได้ในลักษณะเดียวกัน คือให้จัดการดิสก์ที่นำเข้ามาเพิ่มให้ทำงานเป็น RAID ที่ไม่สมบูรณ์ หรือ degraded ก่อน แล้วดัดแปลงขั้นตอนจากข้างบนได้เลย</div>
<div>
<br /></div>
<div>
มีข้อควรระวังคือพาร์ทิชันที่จะใช้ boot (ปกติคือ /boot หรือถ้าไม่ได้แยกไว้ ก็จะเป็น /) ต้องกำหนดเป็น RAID1 และใช้ metadata version 0.9 เสมอ ถ้าเป็นแบบอื่น อาจจะบูตไม่ได้ แต่ไม่แน่ใจว่า grub2 นี่รองรับ MD RAID ได้ขนาดไหนแล้ว</div>
kamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com0tag:blogger.com,1999:blog-6885844.post-7079707799564720852011-08-29T14:29:00.000+07:002011-08-29T14:29:42.916+07:00การ downgrade php เป็นรุ่น 5.2.x ใน Debian 6.0 (Squeeze)เมื่อติดตั้ง Debian 6.0 จะได้ php5 เป็นรุ่น 5.3.x ซึ่งมีคุณสมบัติบางประการต่างไปจากรุ่นเดิมคือ 5.2.x (อ่านเพิ่มเติมที่ <a href="http://php.net/manual/en/migration53.php">http://php.net/manual/en/migration53.php</a>) ซึ่งในบางครั้งเรายังจำเป็นต้องใช้รุ่นเดิมอยู่ เช่นยังใช้ drupal 5.x ซึ่งยังใช้ไม่ได้กับ php 5.3 (ต้องเป็น drupal รุ่น 6.x ตัวหลังๆ หรือ drupal 7.x) สามารถเลือกติดตั้ง php5 จาก oldstable หรือ Debian 5.0 (lenny) โดยทำได้ดังนี้<br />
<br />
เพิ่ม repository ของ lenny เช่น จากเดิมใน /etc/apt/sources.list มี<br />
<br />
<br />
<span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">deb http://ftp.th.debian.org/debian squeeze main non-free contrib</span><br />
<div><div><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">deb http://ftp.th.debian.org/debian-security squeeze/updates main non-free contrib</span></div></div><div><br />
</div><div>ให้เพิ่ม ของ lenny เข้าไปด้วย เป็น</div><div><br />
</div><div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">deb http://ftp.th.debian.org/debian squeeze main non-free contrib</span></div><div><div><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">deb http://ftp.th.debian.org/debian-security squeeze/updates main non-free contrib</span></div></div></div><div><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"><div style="color: black; font-family: 'DejaVu Sans'; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"><b>deb http://ftp.th.debian.org/debian lenny main</b></span></div><div style="color: black; font-family: 'DejaVu Sans';"><div><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"><b>deb http://ftp.th.debian.org/debian-security lenny/updates main</b></span></div><div><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"><br />
</span></div></div></span></div><div>แก้ไข (หรือสร้างไฟล์ใหม่) /etc/apt/preferences ใส่คอนฟิกดังนี้ลงไป</div><div><br />
</div><div><div><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">Package: <b>php-* php5 php5-* libapache2-mod-php5 php-pear</b></span></div><div><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">Pin: <b>release a=oldstable</b></span></div><div><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">Pin-Priority: <b>999</b></span></div><div><br />
</div></div><div>จากนั้นสั่ง</div><div><br />
</div><div><span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>apt-get update</b></span></div><div><span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>apt-get -f install</b></span></div><div><br />
</div><div>ระบบจะ downgrade แพกเกจ PHP ที่ติดตั้งไปแล้ว ที่อยู่ในรายการที่เรากำหนด ให้เป็นรุ่นที่อยู่ใน oldstable ตามต้องการ ถ้ายังไม่ติดตั้ง ก็ติดตั้งตามปกติ</div><div><br />
</div><div>และเมื่อไหร่ที่พร้อมที่จะอัพเกรด php เป็นรุ่น 5.3 ก็แก้ไฟล์ /etc/apt/preferences เอาคอนฟิกที่เพิ่มเข้าไป 3 บรรทัดนั้นออก แล้วสั่ง upgrade ตามปกติได้เลย</div><br />
kamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com0tag:blogger.com,1999:blog-6885844.post-5530200863505694422011-08-27T08:59:00.002+07:002011-08-27T08:59:00.540+07:00การเปลี่ยน harddisk ใน MD RAID + ประสบการณ์ harddisk เสียพร้อมกัน 2 ตัวปกติเวลาทำ RAID บน server เราจะคาดหวังว่าข้อมูลมันจะปลอดภัยเป็นอันดับแรก โดยหลักการคือเราเชื่อว่าฮาร์ดดิสก์มันจะเสียไม่พร้อมกันหรอก พอเสียก็รีบเปลี่ยนตัวใหม่มาแทนทันที มันก็ควรจะอยู่ไปได้เรื่อยๆ นั่นคือเราคาดว่าฮาร์ดดิสก์มันควรจะเสียทีละตัว มีโอกาสน้อยมากที่มันจะเสียพร้อมๆ กัน<br />
<br />
แต่ก็ไม่ใช่ว่าจะเป็นไปไม่ได้ เร็วๆ นี้ผมเจอเคสหนึ่ง เซิร์ฟเวอร์ที่เคยไปติดตั้งให้ลูกค้าเมื่อ 2 ปีกว่ามาแล้ว ส่งเมลมาแจ้งว่ามีดิสก์ตัวหนึ่งของ RAID เสีย (อันนี้เป็นข้อดีประการสำคัญของ Linux MD RAID ที่มันมีตัว monitor ที่จะส่งเมลบอกเราได้เมื่อพบดิสก์เสีย) ผมก็รีบแจ้งลูกค้าให้เตรียมฮาร์ดดิสก์ไปเปลี่ยน แล้วก็นัดกันเข้าไปเปลี่ยนที่ NOC แห่งหนึ่ง<br />
<br />
เริ่มจาก ตรวจสอบดูสถานะของ RAID โดยสั่ง<br />
<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># cat /proc/mdstat</span><br />
<br />
ถ้าระบบ RAID มันปกติ จะพบสถานะแสดงเป็น [UU] อันนี้เป็นกรณี RAID1 ถ้ามีตัวหนึ่งเสีย จะเป็น [U_] และหลังชื่อ device ที่เสีย จะมี (F) บอกไว้<br />
ในที่นี้ระบบดังกล่าวผมทำ RAID1 ไว้ 5 ชุด บนดิสก์ 4 ตัว ชุดหนึ่งเป็น RAID1 ที่สร้างจาก partition เล็กๆ 4 partition จากแต่ละดิสก์ เพื่อใช้เป็น /boot และติดตั้ง bootloader ไว้บนทุกดิสก์ นั่นคือระบบนี้จะต้องบูตได้จากดิสก์ทุกตัว แล้วรวมชุดที่เหลืออีกทีเป็น RAID0 2 ชุด สำหรับเก็บข้อมูล<br />
<br />
ในที่นี้ดิสก์ตัวที่เสียคือ sda จึงสั่ง remove ตัวที่เสียออก<br />
<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># mdadm /dev/md0 --remove /dev/sda1</span><br />
<span class="Apple-style-span" style="border-collapse: collapse; color: #0c343d; font-family: 'Courier New', Courier, monospace; font-size: 12px; font-style: italic; line-height: 18px;">mdadm: hot removed /dev/sda1</span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># mdadm /dev/md1 --remove /dev/sda3</span><br />
<span class="Apple-style-span" style="border-collapse: collapse; color: #0c343d; font-family: 'Courier New', Courier, monospace; font-size: 12px; font-style: italic; line-height: 18px;">mdadm: hot removed /dev/sda3</span><br />
<br />
บางทีมันพบจุดเสียเฉพาะในบางพาร์ทิชัน แต่เราต้องเปลี่ยนด้วยกัน ก็ให้สั่ง fail มันก่อนแล้วค่อย remove<br />
<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># mdadm /dev/md1 --fail /dev/sda3 --remove /dev/sda3</span><br />
<span class="Apple-style-span" style="border-collapse: collapse; color: #0c343d; font-family: 'Courier New', Courier, monospace; font-size: 12px; font-style: italic; line-height: 18px;">mdadm: hot removed /dev/sda3</span><br />
<span class="Apple-style-span" style="border-collapse: collapse; font-size: 12px; line-height: 18px;"></span><br />
<div style="font-family: verdana, sans-serif;"><br />
</div>เครื่องนี้มี hot swap bay ซึ่งมีหลอดแสดงสถานะการทำงานของดิสก์แต่ละตัวแยกกัน แต่เนื่องจากไม่ได้ใช้ hardware RAID จึงไม่มีไฟบอกสถานะว่าดิสก์ตัวไหนเสีย จึงเล่นมุกง่ายๆ โดยลองสั่งให้ดิสก์ตัวที่เสียมันทำงาน โดยสั่ง<br />
<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># dd if=/dev/sda of=/dev/null bs=1G count=1</span><br />
<br />
ไฟหลอดไหนกระพริบก็แสดงว่าคือตัวนั้น จึงถอดออกและใส่ตัวใหม่แทน แต่พบว่าปัญหาคือ hotswap มันทำงานผิดปกติหรือเปล่าไม่ทราบ ตัวใหม่จึงเห็นเป็น sde ซึ่งเป็นไปได้มากกว่าพอบูตใหม่ มันจะกลับมาแสดงเป็น sda แทนตัวเก่าอีกที แต่อันที่จริงไม่น่าจะมีปัญหาเพราะ RAID มันจะตรวจสอบจาก uuid ของ partition ไม่ใช่ชื่อ device<br />
<br />
ขั้นต่อไปคือสร้างพาร์ทิชันให้เหมือนของเดิม ในที่นี้ดิสก์ทุกตัวถูกสร้างให้มีพาร์ทิชันแบบเดียวกันหมด จึงทำได้ง่ายๆ โดยการโคลนโครงสร้างพาร์ทิชันด้วย sfdisk<br />
<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># sfdisk -d /dev/sdb | sfdisk /dev/sde</span><br />
<br />
และเพิ่มดิสก์ใหม่เข้าไปใน RAID<br />
<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># mdadm /dev/md0 --add /dev/sde1</span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># mdadm /dev/md1 --add /dev/sde3</span><br />
<br />
ตรวจสอบดู<br />
<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># cat /proc/mdstat</span><br />
<br />
ก็จะพบว่า RAID กำลังถูก rebuild<br />
<br />
อื่นๆ ที่ทำคือติดตั้ง grub ใน boot record เพื่อให้มันบูตได้ ซึ่งยังไม่ขอกล่าวถึงในที่นี้<br />
<br />
ซึ่งทั้งหมดที่ทำนี้เครื่องนี้ยังให้บริการต่อตามปกติ แต่เพื่อความแน่ใจจึงขอรีบูตเครื่องใหม่เพื่อดูว่า RAID ยังทำงานได้ แต่พบว่า BIOS แจ้งว่าพบดิสก์เพียง 3 ตัว ปรากฏว่ามีดิสก์อีกตัวที่เดิมไม่ได้เสีย แต่พอรีบูตเครื่องแล้วไม่สามารถกลับมาทำงานได้ตามปกติ ซึ่งเป็นเรื่องในตำนานที่เคยได้ยินมาเหมือนกันว่า ระบบที่เปิดทิ้งไว้นานนับหลายปี ทำงานปกติดี แต่พอรีบูตแล้ว ดิสก์ไม่กลับมาทำงานอีก แต่ไม่คิดว่าจะเจอกับตัว แถม RAID ยัง rebuild ไม่เสร็จด้วย ตั้งสติกันสักพัก แล้วมาลุ้นกันว่าตัวไหนจะเสีย คือถ้าตัวที่เสียคือตัวที่คู่กับมันใน raid1 ก็โบกมือลาข้อมูลได้เลย แต่โชคดีที่ไปเสียตัวที่ไม่ใช่คู่มัน ไปเสียที่ raid1 อีกชุดหนึ่ง จึงต้องถอดดิสก์ตัวที่เสียอีกตัวให้ลูกค้าเอาไปเคลม โดยปล่อยให้ระบบทำงานในโหมด degraded ไปก่อน แล้วอีกอาทิตย์หนึ่งจึงกลับมาใส่และ rebuild มันคล้ายๆ step ข้างบนอีกรอบ<br />
<br />
เพื่อความปลอดภัย เผื่อในกรณีซวยซ้ำซวยซ้อนแบบที่เจอมานี้ ควรใช้ RAID ที่ยอมให้ดิสก์เสียได้มากกว่า 1 ตัว เช่น RAID6 ที่ยอมให้ดิสก์เสียได้ถึง 2 ตัว (ส่วน RAID5 ยอมให้เสียได้เพียง 1 ตัว) RAID1+0 ก็พอไหว เสียได้ 1 ตัว กับอีกตัวที่ไม่ใช่คู่ของมัน (2 ใน 3 ตัว) อันนี้คือกรณีทำ RAID1 2 ชุด แล้วมารวมเป็น RAID0 อีกชุดหนึ่ง ถ้าทำ RAID0 2 ชุด แล้วมารวมเป็น RAID1 ผมคิดว่าไม่ใช่ไอเดียที่ดี เพราะถ้ามีดิสก์เสีย 1 ตัว อีก 1 ตัวที่จะเสียได้ ต้องเป็นคู่ของมันเท่านั้น (1 ใน 3 ตัว)<br />
<br />
มีอีกแนวทางหนึ่งคือใช้ <a href="http://en.wikipedia.org/wiki/Non-standard_RAID_levels#Linux_MD_RAID_10">Linux MD RAID 10</a> ซึ่งเป็น non-standard RAID ซึ่งสามารถกำหนด layout ได้ว่าให้บันทึกข้อมูลในดิสก์ในลักษณะใด ซึ่งสามารถทำให้ระบบยอมให้ดิสก์เสียได้พร้อมกัน 2 ตัว ไม่ว่าจะเป็นตัวไหนก็ได้ โดย Linux MD RAID 10 นี้ยังให้ประสิทธิภาพทั้งการอ่านและเขียนสูงกว่าแบบอื่นๆ ซึ่งขึ้นอยู่กับ layout ที่เลือกอีกด้วย ไว้โอกาสหน้าจะเอามานำเสนออีกครั้งครับkamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com2tag:blogger.com,1999:blog-6885844.post-76496712423333257232011-08-26T08:59:00.002+07:002011-08-26T08:59:00.071+07:00btrfs: ทำ profile แบบ RAID ในระดับ filesystemคุณสมบัติหนึ่งของ btrfs คือ มันสามารถใช้ดิสก์หลายๆ ตัวมารวมเป็นพื้นที่เดียวกันได้ โดยไม่จำเป็นต้องพึ่ง RAID หรือ LVM ซึ่งสามารถกำหนด metadata profile และ data profie ได้ว่าให้มีคุณสมบัติคล้าย RAID แบบใด ซึ่งปัจจุบันสามารถกำหนดให้เป็น raid0, raid1, raid10<br />
<br />
ตอนสร้าง filesystem แบบ btrfs มันจะใช้ metadate profile เป็น raid1 และ data profile เป็น raid0 ถ้าสร้างบนดิสก์ตัวเดียว metadata จะเก็บบนดิสก์ตัวเดียวกัน 2 สำเนา<br />
<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># mkfs.btrfs /dev/sda1</span><br />
เทียบเท่า<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># mkfs.btrfs -m raid1 -d raid0 /dev/sda1</span><br />
<br />
สร้างจากดิสก์ 2 ตัว<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># mkfs.btrfs /dev/sda1 /dev/sdb1</span><br />
เวลาเมานท์ก็ระบุตัวใดตัวหนึ่งก็ได้เช่น<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># mount /dev/sda1 /mnt/data</span><br />
<br />
อันที่จริงแล้วมันไม่ได้เป็น RAID จริงๆ คือไม่ได้เป็นลักษณะของ disk array แต่เป็นการกำหนดว่าหน่วยข้อมูลที่จัดเก็บใน filesystem บนดิสก์หลายๆ ตัว ให้มีลักษณะของการเก็บอย่างไร ได้แก่<br />
<br />
<b>raid0</b><br />
เก็บหน่วยข้อมูลในลักษณะ stripping คือกระจายหน่วยข้อมูลที่ต่อเนื่องกัน ให้ไปอยู่บนดิสก์หลายๆ ตัว ทำให้การอ่านและเขียนเร็วขึ้นมากตามจำนวนดิสก์ที่มี<br />
<br />
ต้องใช้ดิสก์อย่างน้อย 1 ตัว อันนี้จะต่างจาก RAID ปกติ ที่จะต้องใช้ดิสก์ 2 ตัวขึ้นไป คือถ้ามีดิสก์เพียง 1 ตัว มันก็จะเก็บข้อมูลตามปกตินั่นเอง<br />
ถ้าในตอนแรกมีดิสก์ 2 ตัว เมื่อสั่ง delete ดิสก์ออก 1 ตัว มันจะคัดลอกข้อมูลจากตัวที่จะเอาออก มาที่ตัวที่เหลือ แล้วจึงเอาออก ซึ่งในการทำแบบนี้ สามารถทำในขณะที่ filesystem กำลังทำงานอยู่ได้ทันที ในการเพิ่ม ก็สามารถเพิ่มดิสก์เข้ามาได้ทันที โดยสามารถสั่ง balance เพื่อกระจายหน่วยข้อมูลออกไปเก็บบนดิสก์ทุกตัวอีกที<br />
<i>ความปลอดภัยของข้อมูล</i><br />
แบบ raid0 นี้ข้อมูลแต่ละหน่วยมีเพียงชุดเดียว ไม่มีสำเนา หากมีดิสก์ตัวใดตัวหนึ่งเสีย ข้อมูลที่อยู่ในดิสก์ตัวนั้นจะเสียไปเลย<br />
<br />
<b>raid1</b><br />
เก็บข้อมูลหน่วยละ 2 ชุด และอยู่คนละดิสก์กันเสมอ หรือเรียกอีกอย่างหนึ่งว่า mirroring ต้องใช้ดิสก์ 2 ตัวขึ้นไปเสมอ ดังนั้นถ้าตอนแรกสร้างบนดิสก์ 2 ตัว จะสั่ง delete ตัวใดตัวหนึ่งออกไม่ได้เลย แต่ถ้าดิสก์เกิดเสีย ยังสามารถเมานท์แบบ degrade ได้เพราะข้อมูลมีครบทั้งสองตัว<br />
<br />
ตัวอย่าง<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># mkfs.btrfs -d raid1 /dev/sda1 /dev/sdb1 /dev/sdc1 /dev/sdd1</span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># mount /dev/sda1 /mnt/data</span><br />
<br />
<b>raid10</b><br />
เก็บข้อมูลหน่วยละ 2 ชุดคนละดิสก์กัน และเรียงข้อมูลแบบ stripping ด้วย ทำให้ได้ทั้งความปลอดภัย และความเร็วในการอ่านและบันทึกข้อมูล แบบนี้ใช้ดิสก์ 4 ตัวขึ้นไปเสมอ ถ้ามีเพียง 4 ตัวจะ delete ตัวใดตัวหนึ่งออกไม่ได้<br />
<br />
ตัวอย่าง<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># mkfs.btrfs -m raid10 -d raid10 /dev/sd[a-d]1</span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># mount /dev/sda1 /mnt/data</span><br />
<br />
สามารถเพิ่มดิสก์เข้าไปใน pool ของมันได้เรื่อยๆ เช่นเพิ่มดิสก์ตัวที่ 5 เข้ามา ก็สร้าง partition แล้วเพิ่มเข้ามาได้เลย<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># btrfs device add /dev/sde1 /mnt/data</span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># btrfs filesystem balance /mnt/data</span><br />
สังเกตว่าไม่ต้อง mkfs.btrfs แล้ว แค่เพิ่มเข้าไปเลย และหลังจากเพิ่ม สามารถสั่ง balance เพื่อกระจายข้อมูลไปยังดิสก์ตัวใหม่ด้วย<br />
<br />
การถอดดิสก์ออกจาก pool ใช้คำสั่งตามตัวอย่างนี้<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># btrfs device delete /dev/sde1 /mnt/data</span><br />
<br />
การเมานท์เมื่อมีดิสก์บางตัวเสียหาย หรือถูกถอดออกไปโดยไม่ได้สั่ง delete<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># mount -o degraded /dev/sda1 /mnt/data</span><br />
ซึ่งก็ควรจัดหาดิสก์มาทดแทนให้เร็วที่สุดแล้วสั่ง<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># btrfs device add /dev/sde1 /mnt/data</span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># btrfs device delete missing /mnt/data</span><br />
<br />
ข้อสังเกตจากการทดลองใช้งานจริงมาระยะหนึ่ง<br />
<br />
<ol><li>data profile raid1 เวลาสร้างบนดิสก์ที่มากกว่า 2 ตัว มันชอบเอาข้อมูลไปกองอยู่บนดิสก์แค่ 2 ตัว ไม่ค่อยกระจายเท่าไหร่ ทำให้ดิสก์บางตัวทำงานหนัก ขณะที่บางตัวไม่ค่อยถูกใช้งาน เมื่อสั่ง balance ยิ่งทำให้ข้อมูลถูกย้ายมาเก็บแค่ 2 ตัว</li>
<li>data profile raid10 เวลาถอดดิสก์ออกจากเครื่อง แล้วสั่งเมานท์ จะเมานท์ไม่ได้ แม้ว่าจะระบุอ็อพชัน -o degraded แล้วก็ตาม ส่วนแบบ raid1 ยังไม่ได้ลอง</li>
<li>กำหนด layout ของการเก็บข้อมูลไม่ได้ จึงไม่สามารถระบุให้เก็บข้อมูลเป็น 3 ชุด แทนที่จะเป็น 2 ชุดได้ ซึ่งทำให้เสี่ยงที่จะเกิดปัญหาถ้ามีดิสก์เสีย 2 ตัวพร้อมๆ กัน</li>
<li>ยังไม่รองรับ profile แบบ raid5, raid6</li>
<li>ยังเปลี่ยน profile ไม่ได้ ถ้าสร้างแบบไหน ก็ต้องใช้แบบนั้นตลอดไป</li>
<li>แต่ละ subvolume ไม่สามารถกำหนด profile แตกต่างกันได้</li>
<li>การ balance ทำได้ช้ามาก</li>
<li>สามารถสั่ง defragment ได้ แต่ก็ช้ามากเช่นกัน</li>
<li>ยังไม่สามารถสั่งตรวจสอบ filesystem แบบ online คือกำลังเมานท์อยู่ได้ และการตรวจสอบแบบ offline ก็ยังไม่สมบูรณ์</li>
</ol><div>โดยรวมๆ ยังมีหลายๆ อย่างไม่สมบูรณ์ แต่โดยส่วนตัวคิดว่า เมื่อสมบูรณ์กว่านี้ เราคงไม่จำเป็นต้องใช้ RAID อีกต่อไป</div>kamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com0tag:blogger.com,1999:blog-6885844.post-74329437632661372182011-08-25T08:59:00.053+07:002011-08-25T08:59:00.558+07:00ขอคืนพื้นที่ /var/log โดยการ compress log ด้วย xzxz คล้ายๆ gzip แต่ compress ด้วยอัลกอริทึ่ม lzma2 มีใน squeeze ขึ้นมา หรือใน lenny-backports ดูเพิ่มเติมที่ <a href="http://tukaani.org/xz/">http://tukaani.org/xz/</a><br />
<b><br />
</b><br />
<b>ทำไมต้องใช้ xz แทน gzip</b><br />
<ul><li>บีบได้เยอะกว่ามาก พอเอามาใช้บีบ log เก่าที่ถูก rotate ทำให้ใช้พื้นที่น้อยลงมาก</li>
<li>ตอน decompress ทำได้ค่อนข้างเร็ว ช้ากว่า gunzip บ้าง แต่เร็วกว่า bunzip2 มาก</li>
</ul><b>ข้อเสีย?</b><br />
<ul><li>ใช้เวลา compress นานกว่ามาก เพราะใช้กำลังในการประมวลผลเยอะ (+ram เยอะๆ) แต่มันทำครั้งเดียว และก็ cpu กับ ram ไม่น่าเป็นปัญหากับ server ในปัจจุบันนัก ส่วนการอ่าน/นำไปใช้ก็มี xzcat, xzless ให้ เร็วใกล้เคียงกับ zcat, zless เลยทีเดียว</li>
</ul><b>ติดตั้ง</b><br />
<div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># apt-get install xz-utils</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># apt-get install xz-lzma </span></div><div style="color: #333333; font-family: 'lucida grande', tahoma, verdana, arial, sans-serif; line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><b><span class="Apple-style-span" style="font-family: inherit;">เทียบคำสั่ง</span></b></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">gzip : xz</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">gunzip : unxz</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">zcat : xzcat</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">zless : xzless</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">zmore : xzmore</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">zgrep : xzgrep</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">zdiff : xzdiff</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">zcmp : xzcmp</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">zegrep : xzegrep</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: inherit;"><br />
</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: inherit;">การประยุกต์ใช้กับ logrotate เพื่อขอคืนพื้นที่ใน /var/log</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: inherit;">เพิ่มบรรทัดต่อไปนี้เข้าไปใน /etc/logrotate.conf</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">#---------------------------------</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">compresscmd /usr/bin/xz</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">uncompresscmd /usr/bin/unxz</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">compressext .xz</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">compressoptions -9</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;">#---------------------------------</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: inherit;"><br />
</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><b><span class="Apple-style-span" style="font-family: inherit;">การแปลงจาก log เก่าที่เป็น .gz มาเป็น .xz</span></b></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><i><span class="Apple-style-span" style="font-family: inherit;">แปลงไฟล์เดียว</span></i></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># gunzip access.log.2.gz</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># xz -9 access.log.2</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: inherit;"><br />
</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><i><span class="Apple-style-span" style="font-family: inherit;">แปลงหลายๆ ไฟล์</span></i></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># cd /var/log</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># find . -name "*.gz" | sed 's/.gz$//' | xargs -I '{}' -n 1 -P 2 sh -c "gunzip '{}'.gz ; xz -9 '{}'"</span></div><div style="color: #333333; line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: inherit;"><br />
</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: inherit;">* หมายเหตุ ตรง -P 2 นั่นคือทำพร้อมๆ กัน 2 process ถ้า cpu มีหลายๆ core ก็เพิ่มมากกว่านี้ได้ตามความเหมาะสม จะทำให้แปลงได้ไวขึ้น</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: inherit;"><br />
</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: inherit;">ปล. คัดลอกมาจาก note เก่าใน Facebook ของผมเอง</span></div>kamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com0tag:blogger.com,1999:blog-6885844.post-45217867278912331902011-08-24T08:59:00.002+07:002011-08-24T12:03:14.250+07:00btrfs: การสร้าง snapshot ของข้อมูล ด้วยวิธี cp --reflinkใน<a href="http://blog.kamthorn.org/2011/08/btrfs-snapshot.html">ครั้งก่อน</a>เราได้ดูวิธีการทำ snapshot ของ subvolume ใน btrfs ไปแล้ว ซึ่งวิธีนั้นเหมาะกับผู้ที่เป็น admin เพราะมีสิทธิของ root ที่จะทำได้<br />
<div><br />
</div><div>ถ้าเราเป็นผู้ใช้ทั่วๆ ไป แต่มีพื้นที่เก็บข้อมูลบน filesystem แบบ btrfs เราสามารถทำสิ่งที่คล้ายๆ กับการทำ snapshot ได้เช่นกัน แต่จะใช้พื้นที่เยอะกว่าเล็กน้อย และช้ากว่าหน่อยนึงด้วย</div><div><br />
</div><div>วิธีการคือการใช้คำสั่ง cp (copy) โดยใช้อ็อพชั่น --reflink=always กับ -a ซึ่ง -a หรือ --archive คือการคัดลอกทั้ง subdirectory และไม่แปลง soft-link กลับเป็นไฟล์ และรักษาคุณสมบัติของไฟล์ทุกประการไว้</div><div>ส่วน --reflink ใช้กับการคัดลอกแบบ CoW คือไฟล์ที่ได้จะอยู่บนคนละ inode แต่ใน inode ชี้ไปหารายการบล็อคชุดเดียวกันกับต้นฉบับ เว้นแต่เมื่อบล็อคใดมีการแก้ไข จะถูกสำเนาไปเป็นบล็อคใหม่ทันที</div><div><br />
</div><div>เช่น ใน home ของผู้ใช้มีข้อมูลสำคัญเก็บใน Documents ต้องการสำเนาทั้งหมดเก็บไว้แบบ snapshot</div><div><br />
</div><div><span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;">$ mkdir backups</span></div><div><span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;">$ cp -a --reflink=always Documents backups/Documents-20110825</span></div><div><br />
</div><div>การคัดลอกจะใช้เวลาไม่นานนัก เพราะมีการอัพเดทเฉพาะส่วน metadata โดยส่วนข้อมูลยังชี้ไปที่เดิม พื้นที่ของดิสก์จะลดลงเล็กน้อย</div><div><br />
</div><div>สามารถสำเนาแบบนี้ได้อีกหลายๆ ครั้งตามต้องการ เช่น ในวันต่อมาก็สั่ง</div><div><div><span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;">$ cp -a --reflink=always Documents backups/Documents-20110826</span></div></div><div><span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"><br />
</span></div><div>เมื่อต้องการลบ snapshot เหล่านี้ออกบ้าง ก็ใช้คำสั่ง rm -rf ออกได้ เช่น</div><div><br />
</div><div><span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;">$ rm -rf backups/Documents-20110825</span></div><div><br />
</div><div>ซึ่งจะได้คืนเนื้อที่ที่เกิดจากความแตกต่างระหว่าง snapshot กับข้อมูลปัจจุบัน</div><div><br />
</div>kamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com0tag:blogger.com,1999:blog-6885844.post-80512482793967288012011-08-23T08:59:00.002+07:002011-08-23T20:02:18.109+07:00ประหยัดแบนด์วิดธ์ด้วยการดาวน์โหลด Ubuntu daily ด้วย zsync<span class="Apple-style-span" style="font-family: 'lucida grande', tahoma, verdana, arial, sans-serif; font-size: 11px; line-height: 16px;"></span><br />
<div style="color: #333333; line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: inherit;">เร็วด้วย ประหยัดด้วย โดยเฉพาะกับการดาวน์โหลดแผ่น daily-live ซึ่งไม่สามารถใช้ jigdo ได้</span></div><div style="color: #333333; line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: inherit;">มันจะใช้ไฟล์ iso เก่าเป็น seed เพื่อหาส่วนที่ยังใช้ได้ แล้วดาวน์โหลดเฉพาะส่วนที่เปลี่ยนแปลง ซึ่งถ้าไฟล์เก่าไม่มีมันก็ดาวน์โหลดมาทั้งหมด</span></div><div style="color: #333333; line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: inherit;"><br />
</span></div><div style="color: #333333; line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: inherit;">เช่นตัวอย่างนี้คือใช้ไฟล์ของเมื่อวานเป็น seed</span></div><div style="color: #333333; line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: inherit;"><br />
</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #0c343d; font-family: inherit;">$ <b>zsync http://mirror1.ku.ac.th/ubuntu-allimages/daily-live/20110821/oneiric-desktop-amd64.iso.zsync</b></span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: inherit;"><br />
</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #0c343d; font-family: inherit;">reading seed file oneiric-desktop-amd64.iso: *****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #0c343d; font-family: inherit;">Read oneiric-desktop-amd64.iso. Target 90.5% complete. *************************************************</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #0c343d; font-family: inherit;">downloading from http://mirror1.ku.ac.th/ubuntu-allimages/daily-live/20110821/oneiric-desktop-amd64.iso:</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #0c343d; font-family: inherit;">##################-- 91.6% 0.1 kBps TA </span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #0c343d; font-family: inherit;">##################-- 93.4% 0.4 kBps A </span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #0c343d; font-family: inherit;">###################- 95.5% 0.9 kBps A </span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #0c343d; font-family: inherit;">#################### 100.0% 9.8 kBps DONE </span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: inherit;"><br />
</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #0c343d; font-family: inherit;">verifying download...checksum matches OK</span></div><div style="line-height: 1.5em; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="color: #0c343d; font-family: inherit;">used 655728640 local, fetched 69735889</span></div><div style="color: #333333;"><span class="Apple-style-span" style="font-family: inherit;"><br />
</span></div><div><div style="color: #333333;"><span class="Apple-style-span" style="font-family: inherit;">แล้วพอมันออกรุ่นจริง ชื่อไฟล์มันจะเปลี่ยน ก็ให้ระบุชื่อไฟล์เก่า เช่น</span></div><div style="color: #333333;"><span class="Apple-style-span" style="font-family: inherit;"><br />
</span></div><span class="Apple-style-span" style="color: #0c343d;"><span class="Apple-style-span" style="font-family: inherit;">$ zsync -i </span><span class="Apple-style-span" style="line-height: 24px;">oneiric-desktop-amd64.iso</span> http://mirror1.ku.ac.th/ubuntu-releases/natty/ubuntu-11.04-desktop-amd64.iso.zsync</span><br />
<div style="color: #333333;"><br />
</div><div style="color: #333333;">ปล. คัดลอกและดัดแปลงจาก note เก่า ใน Facebook ของตัวเองครับ</div></div>kamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com0tag:blogger.com,1999:blog-6885844.post-72121518270381773242011-08-22T16:54:00.002+07:002011-08-23T20:03:48.639+07:00btrfs: การสร้าง snapshot ของข้อมูลbtrfs เป็น filesystem ของ Linux (น่าจะรองรับในทุก distro ในปัจจุบัน) ที่มีคุณสมบัติอย่างหนึ่งคือ CoW (Copy on Write) คือสามารถคัดลอกไฟล์เป็น 2 ชุดโดยอ้างอิงบล็อกของข้อมูลชุดเดียวกันได้ แต่เมื่อไฟล์ใดมีการแก้ไข จึงจะคัดลอกบล็อกที่แก้ไขเป็นอีกบล็อกหนึ่งแล้วจึงแก้ไขมัน ทำให้เวลาคัดลอกลักษณะนี้ มันใช้เนื้อที่น้อยมาก และจะใช้เนื้อที่เพิ่มขึ้นทีละนิดเมื่อไฟล์มีการเปลี่ยนแปลง และสามารถคัดลอกสำเนาในลักษณะนี้ได้หลายๆ ครั้ง (หลายๆ เวอร์ชัน) โดยที่เนื้อที่ที่ใช้เพิ่มขึ้นเฉพาะส่วนที่เปลี่ยนแปลงของแต่ละเวอร์ชันเท่านั้น<br />
<br />
คุณสมบัตินี้ถูกใช้ในการทำ snapshot ของ filesystem ในระดับของ subvolume ด้วยคำสั่ง<br />
<br />
<blockquote><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> btrfs subvolume snapshot <source> [<dest>/]<name></span></blockquote><br />
โดย <source> ต้องเป็น path ของ subvolume ที่ถูกเมานท์ ส่วน <dest> ต้องเป็น path ที่อยู่ใน subvolume ที่อยู่ใน btrfs pool เดียวกัน<br />
<br />
เช่น<br />
ในระบบมี subvolume ชื่อ @ เมานท์ไว้ที่ / (เป็น root directory)<br />
และ @home เมานท์ไว้ที่ /home<br />
<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>mkdir /backups</b></span><br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>btrfs subvolume snapshot /home /backups/home-20110822</b></span><br />
<span class="Apple-style-span" style="color: #0c343d;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">Create a snapshot of '/home' in '/backups/home-20110822'</span></span><br />
<div><br />
</div><br />
ใน /backups/home-20110822 จะมีข้อมูลเก็บอยู่เหมือนใน ้/home ในขณะเวลานั้นๆ ทันที โดยใช้เนื้อที่เพิ่มขึ้นเพียงเล็กน้อย และใช้เวลาในการทำ snapshot สั้นมากๆ แม้ว่าข้อมูลจะมีเป็นจำนวนมากก็ตาม ซึ่งผู้ดูแลระบบอาจจะแจ้งให้ผู้ใช้ทราบว่า สามารถมาเรียกคืนข้อมูลเก่าๆ ย้อนหลังจาก snapshot ที่เก็บไว้ที่ /backups ก็ได้<br />
<br />
snapshot ที่สร้างขึ้น สามารถแก้ไขได้ โดยไม่กระทบกับข้อมูลปัจจุบัน ซึ่งในทางปฏิบัติเราไม่ควรมาแก้ตรงนี้<br />
<br />
<b>การลบ snapshot</b><br />
เนื่องจากเนื้อของดิสก์จะถูกใช้เพิ่มขึ้น เมื่อข้อมูลปัจจุบันต่างจาก snapshot แต่ละรุ่น ดังนั้นการจะเรียกคืนเนื้อที่ส่วนนี้กลับมา ต้องลบ snapshot เก่าๆ ทิ้งไปบ้าง (อาจจะกำหนดเป็นนโยบายว่า จะเก็บย้อนหลังเพียง 7 วัน แล้วเขียน cron script เพื่อจัดการอัตโนมัติ เป็นต้น)<br />
<br />
คำสั่ง<br />
<blockquote><span class="Apple-style-span" style="color: #274e13; font-family: 'Courier New', Courier, monospace;"> btrfs subvolume delete <subvolume></span></blockquote><br />
เช่น<br />
<span class="Apple-style-span" style="color: #0c343d; font-family: 'Courier New', Courier, monospace;"># <b>btrfs subvolume delete /backups/home-20110822</b></span><br />
<span class="Apple-style-span" style="color: #0c343d;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">Delete subvolume '/backups/home-20110822'</span></span><br />
<div><br />
</div><div><span class="Apple-style-span" style="color: #660000;">ข้อควรระวัง</span>คือ ถ้าทำ snapshot ใน filesystem ที่มีไฟล์ถูกเปิดใช้งานอยู่ เช่น mysql server สำเนา snapshot ที่ได้จะไม่สมบูรณ์เพราะไฟล์ที่เปิดอยู่มักจะมีข้อมูลบางส่วนค้างอยู่ในหน่วยความจำ ยังไม่ได้ถูกบันทึกในไฟล์จริง ดังนั้นก่อนจะทำ snapshot ควรปิดระบบที่อาจจะเปิดไฟล์ค้างอยู่ก่อน (ในที่นี้คือให้ปิดโปรแกรม mysql server ก่อน) แล้วจึงสั่งทำ snapshot</div><div><br />
</div><div>ถ้าระบบของเราใช้ btrfs ที่มี data profile และ metadata profile เป็นแบบ RAID1 หรือสร้างบนระบบ RAID1, RAID10, RAID5/6 ไม่ว่าจะเป็นซอฟต์แวร์หรือฮาร์ดแวร์แล้วละก็ อาจจะกล่าวได้ว่า</div><blockquote><span class="Apple-style-span" style="font-size: large;">"ลาก่อน โปรแกรม backup ทั้งหลาย"</span></blockquote>kamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com1tag:blogger.com,1999:blog-6885844.post-22512963529241213932008-09-26T22:24:00.000+07:002011-07-27T12:26:42.283+07:00เสวนา พรบ.ว่าด้วยการกระทำความผิดเกี่ยวกับคอมพิวเตอร์เมื่อวานนี้ (25 กันยายน 2551) ในงานมหกรรมซอฟต์แวร์โอเพนซอร์สแห่งชาติครั้งที่ 8 ซึ่งจัดพร้อมกับงานประชุมวิชาการประจำปีของเนคเทค 2008 ผมได้ทำหน้าที่เป็นพิธีกรดำเนินรายการเสวนา พรบ.ว่าด้วยการกระทำความผิดเกี่ยวกับคอมพิวเตอร์ และ Central Log Server ซึ่งมีแขกรับเชิญ 3 ท่านคือ ร.ต.ท.ดรัณ จาดเจริญ สว.กลุ่มงานตรวจสอบฯ ศูนย์ตรวจสอบและวิเคราะห์การกระทำความผิดทางเทคโนโลยี สำนักงานตำรวจแห่งชาติ คุณสถาพร สอนเสนา จากกลุ่มงานนิติกร สำนักงานปลัดกระทรวงเทคโนโลยีสารสนเทศและการสื่อสาร และคุณสว่างพงศ์ หมวดเพชร จากบริษัทไอทีเบเกอรี่ เป็นหนึ่งในผู้ที่ได้พัฒนาผลิตภัณฑ์และจัดอบรมการทำ Central Log Server ด้วยตนเอง<br/><br/>โดยที่ผมเองก็กล่าวได้ว่ายังขาดความรู้ความเข้าใจการจัดเก็บล็อกให้ถูกต้อง คืออ่านในพรบ.แล้วก็ยังติดใจหลายประเด็น ก็ได้โอกาสซักถามในประเด็นต่าง ๆ ที่ตนสงสัย และเพื่อกันลืม และเป็นข้อมูลให้ผู้อื่นได้รับทราบด้วย ขอลิสต์เป็นประเด็นไปดังนี้<br/><br/><ul><li>ทำไมต้องมี พรบ.นี้ - เพราะการกระทำความผิดเกี่ยวกับคอมพิวเตอร์มีลักษณะที่ต่างไปจากการกระทำความผิดอื่น ๆ เช่น ผู้กระทำความผิดสามารถทำในที่ลับไม่ให้ใครเห็นได้อย่างง่ายดาย ไม่ต้องเปิดเผยตัว พฤติกรรมการกระทำก็ไม่ชัดเจนเหมือนความผิดอื่น ๆ เช่น การขโมยปากกา ก็คือการนำเอาปากกาของผู้อื่นไปเป็นของของตน ปากกาของผู้เสียหาย ก็เห็นได้ขัดเจนว่าไปอยู่กับผู้กระทำความผิด ในขณะที่การขโมยข้อมูลในคอมพิวเตอร์นั้น ข้อมูลเดิมยังอยู่ แต่ผู้กระทำความผิดได้ลักลอบสำเนาออกไปด้วยวิธีกาาต่าง ๆ โดยหาหลักฐานแทบไม่ได้เลย การมีพรบ.นี้ทำให้การกระทำดังกล่าวสามารถระบุความผิดได้ชัดเจนยิ่งขึ้น</li><br/><li>ทำไมต้องเก็บข้อมูลการจราจรทางคอมพิวเตอร์ - เพื่อใช้ประโยชน์ในการสืบสวนสอบสวน และใช้เป็นพยานหลักฐานการเอาผิด ถ้าไม่เก็บ ก็สืบหาผู้กระทำความผิดไม่ได้ จับได้ก็ไม่มีหลักฐาน</li><br/><li>อะไรบ้างที่จะถูกใช้เป็นหลักฐานในการเอาผิด - 1.เนื้อหา เช่นภาพที่อัพโหลดขึ้นเว็บ ข้อความที่โพสต์ 2. ข้อมูลการจราจรทางคอมพิวเตอร์ 3. การระบุตัวตน เช่น ณ เวลาดังกล่าว ใครเป็นผู้ใช้คอมพิวเตอร์ที่เป็นหมายเลขไอพีดังกล่าว ซึ่งการเก็บเวลาที่แม่นยำตรงกัน จะช่วยให้ระบุตัวตนได้ถูกต้อง</li><br/><li>IT Policy - ในองค์กรต้องกำหนด IT Policy ให้ชัดเจนเพื่อให้ผู้ปฏิบัติงานมีความระมัดระวังการใช้คอมพิวเตอร์ที่ปลอดภัยขึ้น เช่นการใช้งานคอมพิวเตอร์ที่มีการใช้ร่วมกัน เมื่อใช้เสร็จต้องล็อกเอาท์ทุกครั้ง เพื่อป้องกันคนอื่นสวมรอยใช้งานในชื่อเรา เป็นต้น</li><br/><li>ถ้าไม่มีเหตุการกระทำความผิดฯ จะมีเจ้าหน้าที่เข้ามาตรวจสอบการเก็บข้อมูลการจราจรทางคอมพิวเตอร์ และฟ้องเอาผิดหรือไม่ - ไม่มี ถ้าเราไม่เก็บข้อมูลการจราจรทางคอมพิวเตอร์ เจ้าหน้าที่จะไม่ทราบเลย จนกระทั่งมีเหตุการกระทำความผิดฯ เกิดขึ้น แล้วเจ้าหน้าที่ขอเรียกดูข้อมูลจากเรา แล้วเราไม่มีให้ เราก็มีความผิดทันที (ประเด็นนี้ยังติดใจอยู่ เพราะเหมือนว่าจริง ๆ แล้วเจ้าหน้าที่มีเพียงไม่กี่คน ไม่ว่างที่จะไปไล่ตรวจสอบด้วยอีกเหตุหนึ่ง)</li><br/><li>ผลิตภัณฑ์สำหรับจัดเก็บข้อมูลจราจรทางคอมพิวเตอร์ที่อ้างว่าได้รับการรับรองจากกระทรวงเทคโนโลยีสารสนเทศและการสื่อสาร เป็นเช่นนั้นจริงหรือไม่ - ไม่จริง กระทรวงฯ ไม่เคยรับรองและไม่มีนโยบายจะรับรองผลิตภัณฑ์จัดเก็บข้อมูลการจราจรทางคอมพิวเตอร์ใด ๆ ถ้ามีแสดงว่าแอบอ้างเพื่อประโยชน์ทางการค้า</li><br/><li>แล้วจะทราบได้อย่างไรว่าผลิตภัณฑ์ฯ ดังกล่าว ทำงานได้ถูกต้องจริง - ให้อ้างอิงจาก พรบ.และประกาศที่เกี่ยวข้อง ว่าคุณสมบัติของผลิตภัณฑ์เป็นไปตาม พรบ.และประกาศหรือไม่ (ผู้ขายต้องรับรองผลิตภัณฑ์ตัวเอง ว่างั้นเถอะ)</li><br/><li>จำเป็นต้องซื้อผลิตภัณฑ์ฯ หรือไม่ - ไม่จำเป็น สามารถทำเองได้โดยใช้เครื่องมือที่เป็นโอเพนซอร์สทั้งหมด โดยต้องลงทุนศึกษา หรือเข้าอบรมก็ทำได้ แต่ถ้าจะให้สะดวก จะใช้บริการจากผู้ให้บริการ ต่าง ๆ ก็ได้</li><br/><li>การทำให้ข้อมูลการจราจรทางคอมพิวเตอร์เชื่อถือได้ ทำอย่างไร - ใน พรบ. ไม่ได้กำหนดว่าทำอย่างไร ขึ้นอยู่กับเทคนิคและความเหมาะสม เช่นการแยก Server กับ Central Log ออกจากกัน การ sign key ใน archive ของ log หรือแม้แต่เก็บ log ตามปกติแต่มีขั้นตอนระเบียบวิธีปฏิบัติที่เชื่อถือได้ว่าไม่มีการดัดแปลงแก้ไข</li><br/><li>ในการสืบสวน หรือแสดงพยานหลักฐานในศาล จะมีการตรวจสอบหรือไม่ว่าข้อมูลดังกล่าวได้รับการจัดเก็บอย่างน่าเชื่อถือจริง - โดยปกติจะไม่ตรวจสอบ ถือว่าผู้จัดเก็บข้อมูลเป็นพยาน ไม่มีส่วนได้ส่วนเสียในการกระทำความผิด เมื่อแสดงพยานหลักฐานอย่างไร ตำรวจ และศาลจะเชื่อตามนั้น ยกเว้นมีเหตุอันเชื่อได้ว่า ผู้จัดเก็บข้อมูลดังกล่าว อาจจะเกี่ยวข้อง รู้เห็นเป็นใจ หรือมีส่วนได้ส่วนเสียกับการกระทำความผิดดังกล่าว หรือถูกสงสัยว่าเป็นผู้กระทำความผิดเสียเอง</li><br/><li>การจัดเก็บข้อมูลการจราจรด้วยวิธี sniff สามารถใช้ได้หรือไม่ - ไม่แนะนำให้ใช้วิธีดังกล่าว เนื่องจากเสี่ยงต่อการขัดต่อมาตราอื่นบางมาตรา ซึ่งจะทำให้ไม่สามารถนำมาใช้เป็นพยานหลักฐานได้ และมีเทคนิคอื่น ๆ ที่ไม่ต้องใช้วิธีการ sniff</li><br/><li>ร้านอินเทอร์เน็ตคาเฟ่ ควรจัดเก็บข้อมูลอย่างไร - 1. จัดเก็บข้อมูลจราจรทางคอมพิวเตอร์ตามปกติ (คือยังไงก็ต้องมี gateway ที่เก็บ log อยู่ดี) 2. ผู้ใช้บริการต้องแสดงบัตรให้เจ้าหน้าที่ลงบันทึกหมายเลขบัตร และบันทึกเวลาใช้งาน เครื่องที่ใช้ทุกครั้ง ชาวต่างชาติก็ต้องแสดงพาสปอร์ต</li><br/><li>ทำไมร้านเน็ตฯ ถูกเพ่งเล็งเป็นพิเศษ - ร้านอินเทอร์เน็ตคาเฟ่เป็นสถานที่สาธารณะที่มีคนเข้าออกเยอะ ถ้าร้านไหนไม่เข้มงวดเรื่องการจัดเก็บข้อมูลจะเป็นแหล่งให้ผู้กระทำความผิดเลือกใช้เป็นที่ก่อเหตุได้</li><br/><li>ประเด็น Free Wi-Fi - 1. Free Wi-Fi ควรมีการออกรหัสให้ผู้ใช้ที่มีการลงทะเบียนด้วยหมายเลขบัตรฯ เท่านั้น มิฉะนั้นจะเป็นแหล่งเอื้อให้กระทำความผิดได้ 2. ระวัง Free Wi-Fi ปลอม ที่แอบเปิดให้บริการเพื่อดักจับ ID และรหัสผ่าน โดยเฉพาะที่ตั้งชื่อเลียนแบบ Wi-Fi อื่น ๆ แถว ๆ นั้น</li></ul><br/><br/>ฝากให้รับฟังไว้ครับ เพราะหลายประเด็นไม่ได้ระบุชัดเจนใน พรบ. ซึ่งอาจจะมีแนวทางปฏิบัติเปลี่ยนไปในอนาคตก็ได้kamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com3tag:blogger.com,1999:blog-6885844.post-1615879440721782492008-09-19T23:38:00.000+07:002011-07-27T12:26:42.283+07:00Linux Virtualization3-4 คืนมานี้สนุกกับการทดลองเล่นกับ virtualization เพราะมีโอกาสได้ลองกับ server ขนาด quadcore 2 CPU ก่อนนี้ใช้ <a href="http://linux-vserver.org/">Linux Vserver</a> อยู่แล้ว และยังใช้งานจริงถึงปัจจุบัน และคิดว่าที่ดีกว่าคือ <a href="http://wiki.openvz.org/">OpenVZ</a> อย่างน้อยมันกำหนด quota ต่าง ๆ ได้ดีกว่า เช่น CPU, memory, disk quota สามารถสร้าง template ของ guest os ง่าย ดูแล้วเหมาะมากที่จะนำไปให้บริการ <a href="http://en.wikipedia.org/wiki/Virtual_private_server">VPS</a><br/><br/>OpenVZ มีข้อดีแบบเดียวกับ Linux Vserver คือไม่ได้กันเนื้อที่ disk และ memory แยกออกมาจาก host OS แบบขาดเลยเหมือนอันอื่น แต่เป็นลักษณะการแชร์กัน เสมือนอยู่บนระบบเดียวกันนั่นแหละ disk image ก็ไม่ต้องสร้าง เก็บ quest OS ไว้ใน directory อันหนึ่ง ทำให้ disk space ก็แชร์กัน ซึ่งดู ๆ แล้วก็คล้าย ๆ กับการใช้ chroot เลย แต่มันมีอะไรลึกซื้งกว่านั้นเยอะ ข้อจำกัดของ Vserver กับ OpenVZ มีแค่ว่าต้องเป็น Linux ด้วยกันเท่านั้นเอง อาจจะต่าง distro กันได้ เรื่อง Vserver กับ OpenVZ ไว้จะเขียนโดยละเอียดอีกที<br/><br/>อีกอันที่สนุกมากคือ KVM ที่มีข้อดีตรงใช้ความสามารถของ virtualization technology ที่มีใน CPU รุ่นใหม่ ๆ ทั้ง Intel และ AMD ทำให้ทำงานได้เร็วมาก โดย KVM นั้นมีส่วนที่เป็น kernel module และส่วนที่เป็น user space ซึ่งอันหลักก็ต่อยอดมาจาก qemu ที่มีชื่อเสียงอยู่ก่อนแล้ว ถ้าใช้ qemu เป็น ก็ใช้ KVM ไม่ยากเลย ซึ่ง KVM ก็ทำให้เป็นไปได้ที่จะมี Windows Server รันอยู่ใน Linux Server อีกทีได้<br/><br/>เรื่องที่ยากหน่อยคือการทำ network interface bridge ซึ่งถึงตอนนี้ก็ยังทำไม่ได้ ลองอ่านจากในเน็ตหลาย ๆ ที่แล้ว เลยต้องเลี่ยงทำ network ภายใน แล้วใช้ iptables เปลี่ยนทางของข้อมูลแทน<br/><br/>ส่วน XEN นี่ยังไม่มีโอกาสได้ลองซักที ไว้ว่าง ๆ จะลองดูหน่อยkamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com0tag:blogger.com,1999:blog-6885844.post-58724885610639589782008-07-02T02:24:00.000+07:002011-07-27T12:26:42.283+07:00Installing Debian Etch with 256MB USB Memory Stickมีครั้งหนึ่งผมได้รับโจทย์ให้ติดตั้ง server โดยที่ server ที่จะซื้อใหม่นั้นไม่มี cd-rom มาด้วย เข้าใจว่าเป็นเหตุผลด้านราคา ซึ่งในทางปฏิบัติก็คิดว่า server ทุกตัว คงได้ใช้ cd-rom เฉพาะตอนติดตั้ง และตอนอัพเกรด หรือแก้ไขปัญหาต่าง ๆ เท่านั้น นอกนั้นก็ไม่ได้ใช้เลย จึงไม่จำเป็นแล้วที่ server จะมี cd-rom ทีนี้ปัญหาจึงเป็นว่า จะติดตั้ง Debian โดยไม่ใช้ cd-rom ได้อย่างไร คิดแบบเร็ว ๆ ก็คือใช้ USB memory stick ไงล่ะ<br/><br/>แล้วจะทำได้อย่างไร ? ถาม Google จึงพบกับ<a href="http://www.debian.org/releases/stable/i386/ch04s04.html.en">วิธีการในคู่มือของ Debian เองเลย</a> ถึงได้รู้ว่า Debian เค้าเตรียมเรื่องแบบนี้ไว้อยู่แล้วแฮะ ขอสรุปสั้น ๆ เป็นวิธีการที่ผมทำตามขั้นตอนในเว็บดังกล่าวดังต่อไปนี้<br/><font color="#ff0000"><b>คำเตือน: บางขั้นตอนต่อไปนี้เป็นคำสั่งที่ต้องใช้สิทธิของ root ซึ่งหลายคำสั่งเป็นอันตรายหากสั่งอย่างไม่ถูกต้อง ดังนั้นโปรดอ่านให้เข้าใจและทำตามอย่างระมัดระวัง</b></font><br/><ol><br/><li>แน่นอนต้องมี USB memory stick ก่อน ส่วนความจุนั้น ขึ้นอยู่กับว่าเราอยากใส่ระบบติดตั้งแบบไหน ผมกะว่าจะติดตั้งแค่แบบ netinst ซึ่งตัว iso มันแค่ 150 MB เอง ดังนั้น USB memory stick ตัวเก่า ๆ 256MB ของผม น่าจะได้ใช้ประโยชน์ก็คราวนี้แหละ และก็ถ้ามีข้อมูลที่ต้องการใช้อยู่ ก็คัดลอกออกจาก USB memory stick เสียให้เรียบร้อย จากนั้นก็ลองเช็คนิดนึงว่า USB memory stick ของเราเสียบที่ช่อง usb แล้วจะเห็นเป็น device อะไร ปกติจะเห็นเป็น /dev/sda แต่หลัง ๆ ก็ไม่แน่ เพราะถ้าฮาร์ดดิสก์ใช้ SCSI (คงน้อย) หรือ S-ATA มันจะใช้ sda ไปแล้ว ซึ่งคงจะเห็น USB เป็น sdb หรือ sdc หรืออื่น ๆ แทน ดังนั้น ในขั้นตอนต่อ ๆ ไปผมจะใช้ /dev/sdX แทนนะครับ ให้เปลี่ยน X เป็นตัวที่ถูกต้องต่อไป</li><br/><li>แบ่งพาร์ทิชันใหม่ เนื่องจากเดิมนั้น เจ้า USB memory stick ของผมเป็นแบบ partitionless คือไม่มีการแบ่งพาร์ทิชัน แล้วใช้ทั้งตัวเป็นที่เก็บข้อมูลเลย เวลาใช้บนลินุกซ์ก็จะเมานท์ /dev/sdX มาใช้เลย ไม่ได้เป็น sdX1<br/>โดยการแบ่งจะใช้คำสั่ง dd เพื่อล้าง sector แรกก่อน และใช้ fdisk เพื่อสร้างพาร์ทิชัน โดย<br/><pre># dd if=/dev/zero of=/dev/sdX bs=512 count=1<br/># fdisk /dev/sdX<br/></pre><br/>กด n (สร้าง partition)<br/>กด p (เลือก primary partition)<br/>กด 1 (เลือก partition ที่ 1)<br/>กด enter เฉย ๆ เพื่อเริ่มจาก cylinder แรก<br/>กด enter เฉย ๆ เพื่อสิ้นสุดที่ cylinder สุดท้าย<br/>กด a เพื่อกำหนดให้ partition บูตได้<br/>กด 1 กำหนดให้บูตจาก partition 1<br/>กด w เพื่อบันทึกและออกจาก fdisk</li><br/><li>สร้าง file system<br/><pre># mkdosfs /dev/sdX1<br/></pre><br/>คำสั่ง mkdosfs ถ้าไม่มี ให้ติดตั้ง dosfstools ก่อนโดย apt-get install dosfstools (ปกติคิดว่ามีอยู่แล้วนะ)</li><br/><li>ติดตั้ง syslinux สำหรับทำหน้าที่เป็น boot loader<br/><pre># apt-get install mtools syslinux<br/># syslinux /dev/sdX1</pre></li><li>เมานท์ USB memory stick ไปที่ตำแหน่งชั่วคราวซักที่หนึ่งก่อน<br/><pre># mkdir /mnt/tmp<br/># mount /dev/sdX1 /mnt/tmp</pre><br/>จะเห็นแฟ้ม ldlinux.sys อยู่ในนี้แล้ว ไม่ต้องลบหรือทำอะไรกับมันนะครับ ตัวนี้เป็นส่วนหนึ่งของ boot loader</li><br/><li>ดาวน์โหลดไฟล์ vmlinuz และ initrd.gz จาก <a href="http://mirror.in.th/debian/dists/Debian4.0r3/main/installer-amd64/current/images/hd-media/">http://mirror.in.th/debian/dists/Debian4.0r3/main/installer-amd64/current/images/hd-media/</a> ไปเก็บใน /mnt/tmp (รุ่นอื่น ๆ ก็เลือกเอาตามความเหมาะสมนะครับ ณ ปัจจุบันรุ่นที่ stable คือ 4.0r3 และผมก็เลือกติดตั้งเป็นแบบ 64bit ซึ่ง processor ของ server ใหม่ ๆ ในปัจจุบันก็สนับสนุนหมดแล้ว ยกเว้นจะเก่า ๆ จริง ๆ ก็ใช้ i386 แทน)</li><br/><li>สร้างแฟ้ม syslinux.cfg ใน /mnt/tmp โดยมีเนื้อหาดังนี้<br/><pre>default vmlinuz<br/>append initrd=initrd.gz</pre></li><li>ดาวน์โหลดไฟล์ ISO image ตัวติดตั้ง debian จาก <a href="ftp://mirror.in.th/debian_iso/4.0_r3/amd64/iso-cd/">http://mirror.in.th/debian_iso/4.0_r3/amd64/iso-cd/</a> ผมเลือกแบบ netinst ด้วยเหตุผลเรื่องขนาด ดังนั้นจึงเลือกไฟล์ debian-40r3-amd64-netinst.iso แล้วนำไปใส่ไว้ที่ /mnt/tmp เช่นกัน ถ้า USB memory stick ใหญ่กว่านี้เป็น 1GB ก็ดาวน์โหลดแผ่นติดตั้งแผ่นแรกมาลงก็ได้ หรือถ้าน้อยกว่านี้ เช่น 64MB ก็เลือกแบบ businesscard ก็ได้</li><br/><li>unmount แล้วนำไปทดลองบูตดูได้เลย<br/><pre># umount /mnt/tmp</pre></li></ol>kamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com0tag:blogger.com,1999:blog-6885844.post-4787485150387565582008-06-26T23:53:00.000+07:002011-07-27T12:26:42.284+07:00Firefox Download Day 2008 (ควันหลง)ในที่สุดก็ผ่านไปแล้วกับ Firefox Download Day 2008 เมื่อวันที่ 17 มิ.ย. 2551 แต่จริง ๆ เวลาบ้านเรากว่าจะดาวน์โหลดได้ก็ล่วงเข้าวันที่ 18 ละ ซึ่งเป็นกิจกรรมการตลาดที่ใช้ความร่วมมือของแฟนคลับทั่วโลก ผมก็สนุกกับเขาด้วย ช่วยดาวน์โหลด 2 ครั้ง เป็นเวอร์ชัน Linux กับ Windows ที่จริงโหลดมาก็ไม่ได้ใช้เลย เพราะใน Hardy นั้นก็เป็น Firefox 3.0 อยู่แล้ว สุดท้ายได้ Certificate มา 1 ใบ เท่มาก<br/><br/><a href="http://www.flickr.com/photos/kamthorn/2589298675/" title="Firefox Download Day 2008 Cert. by Kamthorn, on Flickr"><img src="http://farm4.static.flickr.com/3062/2589298675_be4b9433b7.jpg" alt="Firefox Download Day 2008 Cert." width="500" height="379" /></a><br/><br/>ถามว่ากิจกรรมนี้ ทำแล้วได้อะไร ทำไปทำไม บ้างก็บอกว่าทำเอาสถิติไม่เห็นจะมีคุณค่าอะไรเลย โหลดไปใช้หรือเปล่าก็ไม่รู้ บ้างก็เอามาดูเปรียบเทียบเป็นรายประเทศแล้วตีความว่า ประเทศไหนเป็นอย่างไร เช่น ความเจริญทางด้าน IT, เศรษฐกิจ, ความตื่นตัวเรื่อง Open Source เป็นต้น<br/><br/>ในความเห็นส่วนตัวคิดว่า ทำไปแล้ว "สนุกดี" ครับ ถ้ามองลึก ๆ หน่อย ต้องย้ำว่ากิจกรรมนี้ เป็นกิจกรรมทางการตลาดครับ ถ้าเราดูตัวเลขตรง ๆ อาจจะเขวไปได้ว่าความหมายมันคืออะไร แต่จากประสบการณ์ของตัวเองที่ได้ร่วมกิจกรรมนี้ แล้วได้ชักชวนเพื่อน ๆ ที่รู้จักให้เข้ามาร่วม เลยได้เปิดโอกาสแนะนำ Firefox ไปด้วยว่ามันคืออะไร ดีอย่างไร และก็พบว่ามีแฟน Firefox หลายคนทำแบบเดียวกันนี้ด้วย คิดว่ามีเยอะมากด้วย จำนวนดาวน์โหลดของไทยถึงได้สูงเกินแสนแล้วในวันนี้ ในแผนที่ก็จะเห็นประเทศไทยเป็นสีแดงเข้มแล้ว ดังนั้นเป้าหมายของกิจกรรมนี้จริง ๆ จึงไม่ได้อยู่ที่ตัวชี้วัดชนิด lag (ประมาณดูผลที่ตามมา) นั่นก็คือจำนวนการดาวน์โหลดของประเทศ หรือทั้งโลก แต่อยู่ที่ตัวชี้วัดชนิด lead (คือสิ่งที่พยายามทำเพื่อมุ่งสู่ผลลัพธ์ที่ต้องการ ซึ่งจริง ๆ เราไม่ได้วัด) ที่แฟน Firefox แต่ละคน แต่ละกลุ่มช่วยกันทำขึ้นมามากกว่าครับ<br/><br/>สุดท้ายผลที่ตามมาจริง ๆ คือจำนวนการใช้งาน Firefox ก็จะเพิ่มขึ้นซึ่งคงต้องรอสักพักคงมีสถิติมาให้ดูกัน<br/><br/><b>ลิงก์ที่เกี่ยวข้อง</b><br/>ดาวน์โหลด Firefox 3.0: <a href="http://www.mozilla.com/en-US/firefox/">http://www.mozilla.com/en-US/firefox/</a><br/>แผนที่แสดงยอดดาวน์โหลดแบ่งเป็นประเทศ: <a href="http://www.spreadfirefox.com/en-US/worldrecord/">http://www.spreadfirefox.com/en-US/worldrecord/</a><br/>ข่าวใน Blognone โดยเฉพาะในส่วนความคิดเห็นของสมาชิก: <a href="http://www.blognone.com/node/8102">http://www.blognone.com/node/8102</a><br/>ข่าวใน Mhafai: <a href="http://www.mhafai.com/2008/06/firefox-3-83-million-downloads-24-hours">http://www.mhafai.com/2008/06/firefox-3-83-million-downloads-24-hours</a>kamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com1tag:blogger.com,1999:blog-6885844.post-37318265419302172562008-06-07T00:48:00.000+07:002011-07-27T12:26:42.284+07:00Google Treasure Hunt 2008 Question 4 (prime)ตอนจบของการล่าสมบัติ คือการหา<b>จำนวนเฉพาะที่น้อยที่สุด</b>ที่เป็นผลรวมของ<b>จำนวนเฉพาะที่ต่อเนื่องกัน</b>ตามจำนวนที่ระบุเท่ากัน โดยของผมได้ 15, 31, 127, 515 จำนวน จะบอกว่าเห็นแว๊บแรก มองเห็นว่ามันคือ 2^4-1, 2^5-1, 2^7-1, 2^9+3 ทำให้อดคิดไม่ได้ว่ามันเกี่ยวอะไรกันหรือเปล่า จริง ๆ ไม่ได้เกี่ยวอะไร (มั๊ง)<br/><br/>แต่ข้อนี้ผมทำได้ช้ามาก ๆ เพราะตอนแรกอ่านโจทย์ไม่ละเอียดเอง ไม่ทันสังเกตว่ามันต้องการแค่จำนวนเฉพาะที่ต่อเนื่องกัน ผมนึกว่าจำนวนเฉพาะใด ๆ ก็ได้มาบวกกัน ทำให้โจทย์ยากขึ้นเยอะมาก ซึ่งจริง ๆ เขียนโค้ดจนได้โค้ดที่พร้อมรันแล้ว ซึ่งประเมินแล้วว่ารันนานแน่ ๆ เพราะซับซ้อนมาก ขนาด list ที่ใช้ก็ใหญ่มาก ต้องเก็บข้อมูลเป็น bit เพื่อลดขนาดข้อมูลกันเลยทีเดียว อัพโหลดโค้ด และ text file ที่เก็บจำนวนเฉพาะที่คำนวณไว้แล้ว 6 แสนตัวไปไว้เครื่อง server Linux 64bit ram 8GB รันไปได้หน่อยนึง กะว่าคงต้องรอสักอาทิตย์จึงจะเห็นผล จนแว๊บเห็นคุณ <a href="http://twitter.com/macroart">@macroart</a> tweet บอกว่า<a href="http://blog.macroart.net/2008/06/google-treasure-hunt-puzzle-4-sum-of-prime-numbers.html">เขียนบล็อกเรื่องนี้</a>ไปแล้ว เลยเข้าไปอ่านดูถึงรู้ว่าพลาดไปแล้ว<br/><br/>สรุปว่าเขียนใหม่ครับ เหลือโค้ดไว้ใช้เฉพาะตัวโหลด prime ใน file มาเป็น list ที่เหลือเขียนใหม่เลย ลองแบบยังไม่อ่านแนวทางของคุณ <a href="http://twitter.com/macroart">@macroart</a> แต่สุดท้ายได้แนวคิดคล้าย ๆ กัน คือผมมองเป็นบล็อก เหมือนรถไฟ 4 ขบวนค่อยวิ่งออกจากต้นทาง โดยตอนแรกหาผลรวมเท่าจำนวนที่ระบุของแต่ละขบวนก่อน แล้วค่อย ๆ ขยับรถไฟไปทีละหน่อย โดยลบเลขตัวน้อยท้ายขบวนออก บวกด้วยตัวถัดไปที่อยู่หัวขบวน ค่อย ๆ เทียบค่าทีละคู่ ดังนั้นคู่ที่ 1 กับ 2 จะเริ่มวิ่งก่อน จนกว่าจะได้ผลรวมเท่ากัน ค่อยเทียบกับขบวนที่ 3 และเมื่อทั้ง 3 ขบวนมีผลรวมเท่ากัน ค่อยไปเทียบกับขบวนที่ 4 จนกว่าจะเท่ากันหมด<br/><br/>รอบแรกมีบั๊กนิดหน่อย เพราะการอ้างตำแหน่ง list หัวขบวนผิด พอแก้แล้วก็รันไม่กี่วินาทีก็ได้คำตอบ ช้ากว่าของ <a href="http://twitter.com/macroart">@macroart</a> เพราะรถไฟของแกมีการเร่งเครื่องได้ด้วยถ้าผลรวมต่างกันมาก ๆ ตรงนี้ไม่ได้คิด<br/><br/>ผลลัพธ์ที่ได้คือ<br/><br/><pre>ANSWER = 7448179<br/>[41266, 21229, 5870, 1441] [7448179, 7448179, 7448179, 7448179]<br/>0 : 496459 496471 496477 496481 496487 496493 496499 496511 496549 496579 496583 496609 496631 496669 496681<br/>1 : 240073 240089 240101 240109 240113 240131 240139 240151 240169 240173 240197 240203 240209 240257 240259 240263 240271 240283 240287 240319 240341 240347 240349 240353 240371 240379 240421 240433 240437 240473 240479<br/>2 : 57973 57977 57991 58013 58027 58031 58043 58049 58057 58061 58067 58073 58099 58109 58111 58129 58147 58151 58153 58169 58171 58189 58193 58199 58207 58211 58217 58229 58231 58237 58243 58271 58309 58313 58321 58337 58363 58367 58369 58379 58391 58393 58403 58411 58417 58427 58439 58441 58451 58453 58477 58481 58511 58537 58543 58549 58567 58573 58579 58601 58603 58613 58631 58657 58661 58679 58687 58693 58699 58711 58727 58733 58741 58757 58763 58771 58787 58789 58831 58889 58897 58901 58907 58909 58913 58921 58937 58943 58963 58967 58979 58991 58997 59009 59011 59021 59023 59029 59051 59053 59063 59069 59077 59083 59093 59107 59113 59119 59123 59141 59149 59159 59167 59183 59197 59207 59209 59219 59221 59233 59239 59243 59263 59273 59281 59333 59341<br/>3 : 12041 12043 12049 12071 12073 12097 12101 12107 12109 12113 12119 12143 12149 12157 12161 12163 12197 12203 12211 12227 12239 12241 12251 12253 12263 12269 12277 12281 12289 12301 12323 12329 12343 12347 12373 12377 12379 12391 12401 12409 12413 12421 12433 12437 12451 12457 12473 12479 12487 12491 12497 12503 12511 12517 12527 12539 12541 12547 12553 12569 12577 12583 12589 12601 12611 12613 12619 12637 12641 12647 12653 12659 12671 12689 12697 12703 12713 12721 12739 12743 12757 12763 12781 12791 12799 12809 12821 12823 12829 12841 12853 12889 12893 12899 12907 12911 12917 12919 12923 12941 12953 12959 12967 12973 12979 12983 13001 13003 13007 13009 13033 13037 13043 13049 13063 13093 13099 13103 13109 13121 13127 13147 13151 13159 13163 13171 13177 13183 13187 13217 13219 13229 13241 13249 13259 13267 13291 13297 13309 13313 13327 13331 13337 13339 13367 13381 13397 13399 13411 13417 13421 13441 13451 13457 13463 13469 13477 13487 13499 13513 13523 13537 13553 13567 13577 13591 13597 13613 13619 13627 13633 13649 13669 13679 13681 13687 13691 13693 13697 13709 13711 13721 13723 13729 13751 13757 13759 13763 13781 13789 13799 13807 13829 13831 13841 13859 13873 13877 13879 13883 13901 13903 13907 13913 13921 13931 13933 13963 13967 13997 13999 14009 14011 14029 14033 14051 14057 14071 14081 14083 14087 14107 14143 14149 14153 14159 14173 14177 14197 14207 14221 14243 14249 14251 14281 14293 14303 14321 14323 14327 14341 14347 14369 14387 14389 14401 14407 14411 14419 14423 14431 14437 14447 14449 14461 14479 14489 14503 14519 14533 14537 14543 14549 14551 14557 14561 14563 14591 14593 14621 14627 14629 14633 14639 14653 14657 14669 14683 14699 14713 14717 14723 14731 14737 14741 14747 14753 14759 14767 14771 14779 14783 14797 14813 14821 14827 14831 14843 14851 14867 14869 14879 14887 14891 14897 14923 14929 14939 14947 14951 14957 14969 14983 15013 15017 15031 15053 15061 15073 15077 15083 15091 15101 15107 15121 15131 15137 15139 15149 15161 15173 15187 15193 15199 15217 15227 15233 15241 15259 15263 15269 15271 15277 15287 15289 15299 15307 15313 15319 15329 15331 15349 15359 15361 15373 15377 15383 15391 15401 15413 15427 15439 15443 15451 15461 15467 15473 15493 15497 15511 15527 15541 15551 15559 15569 15581 15583 15601 15607 15619 15629 15641 15643 15647 15649 15661 15667 15671 15679 15683 15727 15731 15733 15737 15739 15749 15761 15767 15773 15787 15791 15797 15803 15809 15817 15823 15859 15877 15881 15887 15889 15901 15907 15913 15919 15923 15937 15959 15971 15973 15991 16001 16007 16033 16057 16061 16063 16067 16069 16073 16087 16091 16097 16103 16111 16127 16139 16141 16183 16187 16189 16193 16217 16223 16229 16231 16249 16253 16267 16273 16301 16319 16333 16339 16349 16361 16363 16369 16381 16411 16417 16421 16427 16433 16447 16451 16453 16477 16481 16487 16493 16519 16529 16547 16553 16561 16567 16573 16603 16607 16619 16631 16633 16649 16651 16657 16661 16673 16691 16693 16699 16703 16729 16741 16747 16759 16763 16787 16811 16823 16829 16831 16843 16871 16879 16883 16889 16901 16903 16921 16927 16931 16937 16943 16963<br/>done.<br/><br/>real 0m21.637s<br/>user 0m16.273s<br/>sys 0m0.328s</pre><br/><br/>7448179 คือจำนวนเฉพาะที่เล็กที่สุด ที่เป็นผลบวกของจำนวนเฉพาะที่ต่อเนื่องกันจำนวน 15, 31, 127 และ 515 จำนวน<br/><br/>ยังไม่เฉลยโค้ดนะครับ ขออุบไว้ก่อน เดี๋ยวไม่สนุก<br/><br/>สรุปว่าได้คำตอบครบทั้ง 4 ข้อแล้ว นอนหลับสนิทซักที เก็บภาพนี้ไว้เป็นที่ระลึก<br/><br/><a href="http://www.flickr.com/photos/kamthorn/2555965960/" title="google-treasurehunt-result by Kamthorn, on Flickr"><img src="http://farm4.static.flickr.com/3016/2555965960_97e43e998e.jpg" width="500" height="266" alt="google-treasurehunt-result" /></a>kamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com3tag:blogger.com,1999:blog-6885844.post-66630895227745379692008-06-06T21:02:00.000+07:002011-07-27T12:26:42.284+07:00Pipe for My Comments on Blognoneผม subscribe เอา <a href="http://feeds.feedburner.com/blognone-comment">comment feed</a> ของ <a href="http://www.blognone.com/">Blognone</a> ไว้ใน <a href="http://reader.google.com/">google reader</a> ซึ่งเยอะจัด ส่วนใหญ่ไม่ค่อยได้ใช้ประโยชน์อะไร มาวันนี้นึกสนุก อยากเก็บ comment ต่าง ๆ ของตัวเองที่ตอบไว้ใน Blognone ทั้งหมดไว้ใน Google reader เลยขอลองสักหน่อย<br/><br/>ปัญหาคือ comment ของ Blognone มีเยอะมาก และแน่นอนว่าไม่ได้แยก user ไว้ให้ เราต้องมา filter เอง พอพูดถึงการ filter feed ก็เลยนึกถึง Yahoo pipes ซึ่งเคยลองเล่นมาบ้างแล้ว สนุกดี ครั้งนี้คงจะเป็นครั้งแรกที่จะเอามาใช้ให้เกิดประโยชน์จริงจังซักที ใช้เวลาไม่นานนักก็สร้าง pipes ขึ้นตามรูป<br/><br/><a href="http://www.flickr.com/photos/kamthorn/2555727798/" title="yahoo-pipe-my-bn-comments by Kamthorn, on Flickr"><img src="http://farm4.static.flickr.com/3029/2555727798_f82df23e8e_o.png" width="456" height="447" alt="yahoo-pipe-my-bn-comments" /></a><br/><br/>อันแรก เป็น source ชนิด feed แล้วมาผ่าน filter เพื่อเลือกเฉพาะที่มี item.dc:creator เป็นตามที่เราระบุใน text input เท่านั้นเอง ก็เรียบร้อย จัดการ save แล้ว publish จากนั้นมาดูวิธีใช้งานกัน<br/><br/>วิธีแรก ดูผ่านหน้าเพจปกติของ Yahoo! pipes โดยเข้าไปที่ <a href="http://pipes.yahoo.com/pipes/pipe.info?_id=f8b3f41bdc451c216630a6c503d61fb5">http://pipes.yahoo.com/pipes/pipe.info?_id=f8b3f41bdc451c216630a6c503d61fb5</a> แล้วกรอก blognone login name แล้วกด "Run Pipe" หรือจะใส่ &name=username ต่อท้าย url เข้าไปเลยก็ได้ แต่จากที่ลองดูพบว่า มันจะได้เฉพาะ comment ท้าย ๆ มาทำ filter ซึ่งบางครั้ง comment ของเรามันตกไปแล้ว<br/><br/>วิธีที่ดีกว่าคือเรียกเป็น feed เพื่อไป เก็บและอ่านใน Google reader โดย subcribe ไปที่ <a href="http://pipes.yahoo.com/pipes/pipe.run?_id=f8b3f41bdc451c216630a6c503d61fb5&_render=rss&name=username">http://pipes.yahoo.com/pipes/pipe.run?_id=f8b3f41bdc451c216630a6c503d61fb5&_render=rss&name=username</a> อย่าลืมเปลี่ยนตรง username เป็นชื่อ login ใน blognone ของคุณเอง<br/><br/>อ๊ะ หรือใครใช้ <a href="http://twitter.com/">twitter</a> จะใช้ <a href="http://twitterfeed.com/">twitterfeed</a> ส่งเข้าไปใน twitter time line ของคุณก็ได้นะ<br/><br/>ใช้แล้วได้ผลอย่างไรบอกเล่ากันด้วยครับkamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com1tag:blogger.com,1999:blog-6885844.post-30891322734098631942008-06-03T08:19:00.000+07:002011-07-27T12:26:42.284+07:00What Punctuation Mark Are You?<table width="350" align="center" border="0" cellpadding="2" cellspacing="0"><tbody><tr><td align="center" bgcolor="#eeeeee"><br/><font style="color: black; font-size: 14pt;" face="Georgia, Times New Roman, Times, serif"><br/><strong>You Are a Colon</strong><br/></font></td></tr><tr><td bgcolor="#ffffff"><br/><center><img src="http://www.blogthingsimages.com/whatpunctuationmarkareyouquiz/colon.gif" width="100" height="100" /></center><br/><font color="#000000"><br/>You are very orderly and fact driven.<br/><br/>You aren't concerned much with theories or dreams... only what's true or untrue.<br/><br/><br/><br/>You are brilliant and incredibly learned. Anything you know is well researched.<br/><br/>You like to make lists and sort through things step by step. You aren't subject to whim or emotions.<br/><br/><br/><br/>Your friends see you as a constant source of knowledge and advice.<br/><br/>(But they are a little sick of you being right all of the time!)<br/><br/><br/><br/>You excel in: Leadership positions<br/><br/><br/><br/>You get along best with: The Semi-Colon<br/></font></td></tr></tbody></table><br/><div align="center"><a href="http://www.blogthings.com/whatpunctuationmarkareyouquiz/">What Punctuation Mark Are You?</a></div>kamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com0tag:blogger.com,1999:blog-6885844.post-78013877484173764202008-05-30T18:21:00.000+07:002011-07-27T12:26:42.284+07:00Optimizing Treasurehunt's Question 1 (robot)เมื่อพิจารณาดี ๆ แล้วพบว่าตาราง list สำหรับใช้คำนวณนั้น มีลักษณะสมมาตรบางส่วน เลยปรับปรุงให้ใช้หน่วยความจำในส่วนที่สมมาตรนั้นเพียงครึ่งเดียว ทำให้ลดการใช้หน่วยความจำได้พอสมควร และการคำนวณใน list ย่อย นั้นใช้เพียง list ก่อนหน้าเท่านั้น ดังนั้นพอคำนวณได้ list ปัจจุบันแล้ว ก็ลบ list ก่อนหน้าทิ้งได้ แต่ผมไม่อยากแก้โค้ดมาก เลยเอาแค่เปลี่ยนเป็น list ว่างพอ ผลคือ<br/><br/><pre lang="python">a=2000<br/>b=2000<br/><br/>if b>a:<br/> a, b = b, a<br/>d=[]<br/>for i in range(a):<br/> d[i:]=[[]]<br/> if i>=b:<br/> x = b<br/> else:<br/> x = i<br/> for j in range(x+1):<br/> if (i == 0) and (j == 0):<br/> d[i][j:] = [0]<br/> elif (i == 0) or (j == 0):<br/> d[i][j:] = [1]<br/> elif i == j:<br/> d[i][j:] = [d[i][j-1]*2]<br/> else:<br/> d[i][j:] = [d[i][j-1] + d[i-1][j]]<br/> if i>0:<br/> d[i-1]=[]<br/><br/>print d[a-1][b-1]</pre><br/><br/>ผลการรัน โดยใช้ time จับเวลา<br/><pre>415828425864924998634542842325676808706232957586556725463361909680781449739748170<br/>786476583991009842613588566821101566552449812050519515271426829403308897930154848<br/>139000401217874574325171349240478804805012554662232593418186105627855887297242750<br/>191258293109799452562416018445296661723328582808673234975864811354576092306731674<br/>226129026615041968499816993517068588780940662630054770440825519413455865220243087<br/>597454080782838938422451159980693138755678460019308423353936671267937407109197183<br/>261946634690754460222691463521097187455850580048349711806796515481309363032514472<br/>631419167126959879296426641287728281408263950661584874428072352076560611103304329<br/>056994774368533971570942013663930927771345889508878174490486498112868394435125871<br/>368770117617083125252317200772612121394477978635381281677951466408518108004063757<br/>181565789433577065739615351320655283808516684687687348436814782925229015434783262<br/>936635458985024720378317210338353260437300968307371995465273889042991687076670199<br/>592582593447226951517354719649532201876810233809966157181452417833096317816478439<br/>040563226541144136090250318325435743209975329838676879857054480550574759550296644<br/>05427578211111064192312240045083183062752759630345186798202023360000<br/><br/>real 0m6.381s<br/>user 0m5.024s<br/>sys 0m0.076s</pre><br/><br/>ลองแก้ขนาดเป็น 4000x4000 คำตอบยาวมากไม่โพสต์แล้วกัน แต่จับเวลาได้<br/><br/><pre>real 0m59.338s<br/>user 0m27.342s<br/>sys 0m0.148s</pre><br/><br/>ทั้งหมดรันบนแล็ปท็อป AMD Turion64 2.2GHz (1 core), RAM 1GBkamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com0tag:blogger.com,1999:blog-6885844.post-59632831857407229982008-05-30T06:29:00.000+07:002011-07-27T12:26:42.284+07:00Google Treasure Huntเล่นมั่ง ๆ<br/><br/>ตอนแรกที่เห็นโจทย์ข้อแรก (robot) สมองกำลังมึน คิดไปมายิ่งปวดหัว เลยเลิกซะ แต่พอเห็นหลาย ๆ คนโพสต์บล็อก เชียร์ว่าไม่ยาก ๆ เอาวะลองดูใหม่ซักตั้ง<br/><br/>เข้าเว็บ <a href="http://treasurehunt.appspot.com/">http://treasurehunt.appspot.com/</a> ปุ๊บคราวนี้ได้ข้อ 3 (network) เลย ลองอันนี้ก่อนละกัน พบว่าง่ายมาก ๆ สำหรับคนที่เข้าใจเรื่อง routing table ของระบบเน็ตเวิร์คแบบ TCP/IP หลักการคือดูว่าจากต้นทางจะไปหาปลายทางต้องเดินผ่าน node ไหนบ้าง เช่นผมเริ่มจาก G ต้องไป A ก็ดูว่า ip ของ A คืออะไร แล้วดูในตารางว่า แถว G มี route ไปหา A ไหม ซึ่งดูได้จากคอลัมน์ของ routing 3 คอลัมน์แรก ถ้ามีก็ให้ไป ip นั้นเลย ถ้าไม่มี ให้ไป default route คือคอลัมน์สุดท้าย เช่นของผมไม่มีใน 3 คอลัมน์แรก ก็ให้ดู ip ในคอลัมน์สุดท้ายซึ่งบอกให้ไป ip หนึ่ง ดูในตารางพบว่าเป็นของ H ก็จดในกระดาษว่า GH แล้วก็ทำเช่นเดียวกันไปเรื่อย ๆ สุดท้ายก็พบว่าเส้นทางเดินคือ GHIJKCOLMBA ก็คือคำตอบที่ต้องส่งไป คำถามนี้ใช้เวลา 2-3 นาทีก็เสร็จ ถูกในครั้งแรกเลยด้วย<br/><br/>ย้อนมาทำข้อ 1 (robot) มีตารางขนาดใหญ่อันหนึ่ง หุ่นยนต์อยู่มุมบนซ้าย ปลายทางอยู่มุมล่างขวา ให้หาจำนวนเส้นทางที่หุ่นยนต์สามารถเดินจากมุมบนซ้ายมามุมล่างขวา โดยให้หุ่นยนต์เดินลง หรือเดินไปทางขวาเท่านั้น วิธีคิดน่าจะมี 2 แนวทางคือ ใช้คณิตศาสตร์ คือเรื่องความน่าจะเป็น กับโปรแกรมมิ่งเอาดื้อ ๆ ซึ่งผมเลือกเขียนโปรแกรม ง่ายกว่าสำหรับผม ก่อนอื่นก็หาแพตเทิร์นของมันให้ได้ก่อน โดยค่อย ๆ คิดโดยมองจากมุมล่างขวาซึ่งเป็นปลายทางว่า<br/><br/>ตารางขนาด 1x1 หุ่นยนต์อยู่ที่ตำแหน่งเดียวกับปลายทาง คำตอบ = 0 <br/>ตารางขนาด 1x2 คำตอบ = 1<br/>ตารางขนาด 1xn คำตอบ = 1<br/>ตารางขนาด nx1 คำตอบ = 1 เช่นกัน<br/><br/>ตารางขนาด 2x2 คำตอบ = 2<br/>ตารางขนาด 2x3, 3x2 คำตอบ = 3<br/>ตารางขนาด 3x3 คำตอบ = 6<br/><br/>ไล่ต่อไปอีกหน่อย ก็เริ่มจับทางได้ว่า จำนวนวิธีการเดินของตารางขนาด mxn ก็คือ จำนวนวิธีการเดินของตารางขนาด (m-1) x n + จำนวนวิธีการเดินของตารางขนาด m x (n-1)<br/><br/>เขียนให้สวย ๆ ก็ได้ว่า f(m,n) = f(m-1,n) + f(m,n-1) แบบนี้มัน recursive ชัด ๆ ว่าแล้วก็จับ python มาเขียนโค้ด ได้ว่า<br/><br/><pre lang="python">def r(a,b):<br/> if (a == 1) and (b == 1):<br/> return 0<br/> elif (a == 1) or (b == 1):<br/> return 1<br/> else:<br/> return r(a-1,b)+r(a,b-1)<br/><br/>m, n = 4, 5<br/>print r(m,n)</pre><br/><br/>ลองค่า m และ n น้อย ๆ ดูแล้วถูกต้องดี อืมม ไม่เลว ๆ แต่พอใส่ค่าจริง ๆ ลงไป คือ 43, 49 ปรากฏว่าเงียบไปนานมาก ดูท่าไม่ดีละ ลองลดลงเหลือ 20, 20 ก็ยังนาน เฮ่ย ไม่ธรรมดาแฮะ แสดงว่าจำนวนทางเดินมันเยอะมาก ทำ recursive ไม่ไหวแล้ว เปลี่ยนมาเป็น array ละกัน<br/><br/><pre lang="python">a=43<br/>b=49<br/><br/>d=[]<br/>for i in range(a):<br/> d[i:]=[[]]<br/> for j in range(b):<br/> if (i == 0) and (j == 0):<br/> d[i][j:] = [0]<br/> elif (i == 0) or (j == 0):<br/> d[i][j:] = [1]<br/> else:<br/> d[i][j:] = [d[i][j-1] + d[i-1][j]]<br/><br/>print d[a-1][b-1]</pre><br/><br/>โชคดีที่ python ใช้เลขจำนวนเต็มขนาดใหญ่ได้ทันที เพราะคำตอบของมันคือ 85182187099351463190080550 ส่งคำตอบเข้าไป ผ่านฉลุย (ถ้าใช้โปรแกรมแรกคิด คงหลายวันเสร็จ)<br/><br/>คำถามข้อที่ 2 ให้ดาวน์โหลดไฟล์ .zip มาไฟล์หนึ่ง พร้อมโจทย์<br/><br/><blockquote> Unzip the archive, then process the resulting files to obtain a numeric result. You'll be taking the sum of lines from files matching a certain description, and multiplying those sums together to obtain a final result. Note that files have many different extensions, like '.pdf' and '.js', but all are plain text files containing a small number of lines of text.<br/><br/>Sum of line 4 for all files with path or name containing stu and ending in .pdf<br/>Sum of line 4 for all files with path or name containing zzz and ending in .js<br/>Hint: If the requested line does not exist, do not increment the sum.<br/><br/>Multiply all the above sums together and enter the product below.<br/>(Note: Answer must be an exact, decimal representation of the number.) </blockquote><br/><br/>โอว แบบนี้ต้องเขียนโปรแกรมเท่านั้น และหนทางหาคำตอบที่ดีที่สุดคือ shell programming ครับพี่น้อง ไม่ยากเลย แต่ครั้งแรกตีโจทย์ผิด อ่านไม่ดีเอง คือคิดว่าชื่อแฟ้มมี stu และนามสกุล .pdf เท่านั้น ที่จริงแล้วในชื่อ path ก็ได้ รอบแรกผิดแค่ตรงนี้เอง<br/><br/>มีอีกจุดที่ต้องระวังคือ โจทย์ให้เอาบรรทัดที่ 4 มา แต่ถ้าจำนวนบรรทัดมีไม่ถึง ก็ไม่ต้องเพิ่มค่า sum ดีที่โจทย์เตือนไว้ เพราะไม่อย่างนั้น ถ้าใช้แค่ head + tail จะได้บรรทัดสุดท้ายมาเสมอ โดยอาจจะไม่ใช่บรรทัดที่ 4 ก็ได้ ผลคือได้ shell script หน้าตาอย่างนี้มา<br/><br/><pre lang="bash">ln1=4<br/>st1="stu"<br/>ext1=".pdf"<br/><br/>ln2=4<br/>st2="zzz"<br/>ext2=".js"<br/><br/>repeat(){<br/> n=1<br/> while [ ${n} -le ${1} ]; do<br/> n=$(($n+1))<br/> echo 0<br/> done<br/>}<br/><br/>s=0<br/>for a in `find . | grep ${st1} | grep ${ext1}$`; do<br/> s=$((`repeat ${ln1} | cat ${a} - | head -n ${ln1} | tail -n 1`+${s}))<br/>done<br/><br/>t=0<br/>for a in `find . | grep ${st2} | grep ${ext2}$`; do<br/> t=$((`repeat ${ln2} | cat ${a} - | head -n ${ln2} | tail -n 1`+${t}))<br/>done<br/><br/>echo "s= ${s}"<br/>echo "t= ${t}"<br/>echo "s*t= $((${s}*${t}))"</pre><br/><br/>ซึ่งผมได้คำตอบคือ 2683982036 ส่งไปในครั้งที่สองก็ถูกต้องเรียบร้อยดี<br/><br/>รออาทิตย์หน้าจะมีคำถามใหม่มาอีก แต่ไม่รู้วันไหน เห็นว่าตอบถูกหมดเป็นคนแรกมีรางวัลให้ ทำอย่างไรจะได้เป็นคนแรกล่ะนี่ เอาน่าเผื่อมีรางวัลปลอบใจเป็น invite ให้ลองใช้ google app engine ก็คงจะดีkamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com0tag:blogger.com,1999:blog-6885844.post-35561783304701447302008-05-13T00:57:00.000+07:002011-07-27T12:26:42.285+07:00Thai Font Tuning in Hardy 1ใน Ubuntu Hardy (8.04) มีฟอนต์ไทยใหม่มาให้ใช้ 3 ตัว คือ Waree, Umpush และ Sawasdee โดยเฉพาะ Waree นั้นถูกกำหนดให้เป็นฟอนต์ปริยายแทน Loma แล้ว ดังนั้นเมื่อติดตั้งครั้งแรกจะเป็นหน้าตาฟอนต์แปลกไปไม่คุ้นตา ก็ด้วยเหตุนี้นี่เอง<br/><br/>ในตอนแรกนี้จะปรับแต่งฟอนต์เพียงเล็กน้อย โดยยังคงใช้ Waree เหมือนเดิม ก่อนอื่นมาดูก่อนว่าปัญหาที่เราจะพบคืออะไร<br/><br/><a href="http://www.flickr.com/photos/kamthorn/2486200050/" title="1-default by Kamthorn, on Flickr"><img src="http://farm3.static.flickr.com/2366/2486200050_1b8ba45c56.jpg" alt="1-default" height="413" width="500" /></a><br/><br/>ดูกันใกล้ ๆ<br/><br/><a href="http://www.flickr.com/photos/kamthorn/2486200052/" title="1-default-1 by Kamthorn, on Flickr"><img src="http://farm3.static.flickr.com/2074/2486200052_2cc7ec436f_o.png" alt="1-default-1" height="188" width="138" /></a> <a href="http://www.flickr.com/photos/kamthorn/2486200054/" title="1-default-2 by Kamthorn, on Flickr"><img src="http://farm3.static.flickr.com/2162/2486200054_0bcd81100d_o.png" alt="1-default-2" height="292" width="435" /></a><br/><br/>นี่คือปัญหาที่เราจะพบเมื่อติดตั้ง Hardy สังเกตว่าตัวอักษรขนาดเล็ก หัวจะหายบ้าง รูตรงหัวตันบ้าง รูปทรงผิดเพี้ยนค่อนข้างมาก ส่วนตัวอักษรที่ใหญ่ขึ้นกลับมีปัญหาที่แปลกไปอีกแบบคือเส้นที่บาง ๆ จะหายไป สังเกตตรงประโยคตัวอย่าง<br/><br/>ปัญหานี้เกิดจาก โดยปกติแล้ว Hardy จะกำหนดให้ใช้ font hinting แบบ native คือเป็น hint ที่ฝังมากับฟอนต์เลย เช่นฟอนต์ Bitstream Vera ซึ่งจะแสดงได้สวยงาม คมชัดไม่เบลอในทุกขนาดตัวอักษร ส่วนฟอนต์ที่ไม่มี hint จะยังคงแสดงเบลอ ๆ เหมือนเดิม แต่ฟอนต์ Waree นั้นมี hint อยู่ด้วย แต่อย่างที่ทราบการดีว่าการทำ hint ให้สมบูรณ์นั้นยากมาก ฟอนต์ Waree จึงแสดงออกมาดีที่สุดได้แบบที่เห็น<br/><br/>ทางแก้แบบง่ายคือ ลดระดับของ hint ลงเหลือแค่ระดับ slight หรือ "นิดหน่อย" โดยเลือกเมนู "ระบบ" --> "ปรับแต่งพื้นโต๊ะ" --> "รูปโฉม" แล้วเลือกแท็บ "แบบอักษร" แล้วคลิกปุ่ม "รายละเอียด..." จากนั้นตั้งค่า Hinting เป็น "นิดหน่อย" ตามภาพ<br/><br/><a href="http://www.flickr.com/photos/kamthorn/2486200056/" title="2-font-render-details by Kamthorn, on Flickr"><img src="http://farm3.static.flickr.com/2260/2486200056_e923500661.jpg" alt="2-font-render-details" height="413" width="500" /></a><br/><br/>ผลคือ<br/><br/><a href="http://www.flickr.com/photos/kamthorn/2486200062/" title="3-screen2 by Kamthorn, on Flickr"><img src="http://farm3.static.flickr.com/2374/2486200062_939bfe6602.jpg" alt="3-screen2" height="413" width="500" /></a><br/><br/><a href="http://www.flickr.com/photos/kamthorn/2486200066/" title="3-screen2-1 by Kamthorn, on Flickr"><img src="http://farm3.static.flickr.com/2355/2486200066_53a3faba3c_o.png" alt="3-screen2-1" height="187" width="138" /></a> <a href="http://www.flickr.com/photos/kamthorn/2485487069/" title="3-screen2-2 by Kamthorn, on Flickr"><img src="http://farm4.static.flickr.com/3212/2485487069_ab3959cb9b_o.png" alt="3-screen2-2" height="291" width="439" /></a><br/><br/>การตั้งระดับ Hint เป็น slight จะทำให้การเรนเดอร์ฟอนต์เน้นที่รูปทรงของฟอนต์มากกว่าความคมชัด ทำให้เห็นได้อย่างชัดเจนว่ารูปทรงของฟอนต์ถูกต้องสวยงาม แต่ก็มีความเบลอมากเช่นกัน และยังทำให้ฟอนต์ภาษาอังกฤษเบลอไปด้วย<br/><br/>สำหรับท่านที่พอใจกับการตั้งฟอนต์แบบนี้ก็หยุดได้เลยครับ แต่สำหรับผมแล้ว ผมต้องการมากกว่านั้น ผมอยากให้ตัวอักษรภาษาอังกฤษชัดเท่าที่มันจะชัดได้ ในขณะที่ภาษาไทยก็ไม่เพี้ยนถึงขั้นเส้นหาย หัวหาย<br/><br/>ทางออกคือ libfreetype ในปัจจุบันมี autohint ซึ่งเป็นวิธีการเรนเดอร์ฟอนต์โดยไม่ต้องพึ่ง hint ที่มาในตัวฟอนต์เอง แต่จะสร้าง hint อัตโนมัติ ซึ่งตัวหลัง ๆ นี่มันทำได้ดีมาก ๆ แต่เราจะใช้ autohint เฉพาะกับฟอนต์ที่เราต้องการ ในที่นี้คือฟอนต์ภาษาไทยเท่านั้น ฟอนต์ที่มี native hint ดี ๆ อย่าง Bitstream Vera เราจะไม่แตะ จะใช้ native hint เหมือนเดิม<br/><br/>ขั้นแรก สร้างแฟ้ม <kbd>.fonts.conf</kbd> ไว้ที่ home ของท่านเองโดยให้มีเนื้อหาดังนี้<br/><br/><pre><?xml version="1.0"?><br/><!DOCTYPE fontconfig SYSTEM "fonts.dtd"><br/><fontconfig><br/> <match target="font"><br/> <test name="family"><br/> <string>Loma</string><br/> <string>Garuda</string><br/> <string>Norasi</string><br/> <string>Kinari</string><br/> <string>Purisa</string><br/> <string>TlwgMono</string><br/> <string>TlwgTypewriter</string><br/> <string>Waree</string><br/> <string>Umpush</string><br/> <string>Sawasdee</string><br/> </test><br/> <edit name="autohint" mode="assign"><bool>true</bool></edit><br/> </match><br/></fontconfig></pre><br/><br/>จากนั้นให้ล็อกเอาท์ออกจากระบบ แล้วล็อกอินเข้ามาใหม่ แล้วตั้งค่าฟอนต์ให้เป็นตามภาพนี้<br/><br/><a href="http://www.flickr.com/photos/kamthorn/2485387805/" title="4-font-render-details-full by Kamthorn, on Flickr"><img src="http://farm3.static.flickr.com/2285/2485387805_f4f336fc12.jpg" alt="4-font-render-details-full" height="413" width="500" /></a><br/><br/>ผลลัพธ์สุดท้าย<br/><br/><a href="http://www.flickr.com/photos/kamthorn/2485387811/" title="5-screen3 by Kamthorn, on Flickr"><img src="http://farm4.static.flickr.com/3061/2485387811_aaf5d6ac5e.jpg" alt="5-screen3" height="413" width="500" /></a><br/><br/><a href="http://www.flickr.com/photos/kamthorn/2485387817/" title="5-screen3-1 by Kamthorn, on Flickr"><img src="http://farm3.static.flickr.com/2088/2485387817_d80fc06721_o.png" alt="5-screen3-1" height="190" width="141" /></a> <a href="http://www.flickr.com/photos/kamthorn/2485387819/" title="5-screen3-2 by Kamthorn, on Flickr"><img src="http://farm3.static.flickr.com/2363/2485387819_076caeb707_o.png" alt="5-screen3-2" height="291" width="441" /></a><br/><br/>จะเห็นว่าตัวอักษรภาษาอังกฤษมีความคมชัดเป็นปกติ ส่วนตัวไทยนั้นมีหัวหาง เส้นต่าง ๆ ครบถ้วน อ่านได้ชัดเจนดี มีเพี้ยนบ้างแต่น้อยมาก ๆ<br/><br/>เป็นอย่างไรครับ เห็นความงามของฟอนต์ Waree หรือยังkamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com5tag:blogger.com,1999:blog-6885844.post-77249799033564012822008-04-26T07:22:00.000+07:002011-07-27T12:26:42.285+07:00เรื่องควรรู้ก่อนลง/อัพเกรดเป็น Hardy Heronเมื่อวาน Ubuntu 8.04 Hardy Heron ออกอย่างเป็นทางการช่วงเย็น ๆ ในประเทศไทย ซึ่งอันที่จริง ผมก็ได้เอามาติดตั้งใช้งานจริง ตั้งแต่ออกเบต้าแล้ว และอัพเกรดมาเรื่อย ๆ<br /><br />มีสิ่งที่คาดหวังไว้จำนวนหนึ่งกับ Hardy แต่ยังพบว่ายังไม่พร้อม อันเนื่องจาก Ubuntu กำหนดการออกรุ่นไว้ตามเวลาเป๊ะ ๆ ต่างจาก Debian ที่ออกเมื่อพร้อม จึงเป็นเรื่องปกติที่ Ubuntu รุ่น release อาจจะไม่ได้ทำงานได้ตามที่คาดหวังเสมอไป จึงขอเอาประสบการณ์ที่พบมาเล่าให้ฟัง<br /><ol><li><strong>Firefox</strong> รุ่นนี้ตั้งธงว่าจะใช้ Firefox 3.0 แต่ก็มีความล่าช้าที่โครงการ Mozilla เองซึ่งในที่สุดแล้วก็เสร็จไม่ทันแน่แล้ว ล่าสุด Firefox 3.0 กำหนดออกประมาณ มิ.ย. 51 ใน Hardy ตั้งใจจะใส่รุ่น 3.0pre แต่ก็ไม่ทัน ดังนั้นรุ่นที่ติดตั้งไปพร้อม Hardy คือ 3.0b5 ซึ่ง บอกตามตรงว่ายังไม่เสถียรพอ ใช้งานปกติ ยังมี crash ให้เห็นเป็นพัก ๆ วันละ 3-5 ครั้ง บางวันต้องถอยไปใช้ firefox-2 แทน แต่ก็อึดอัดกับข้อจำกัดบางอย่าง<br />ทางออกทาง Hardy จะอัพเกรด Firefox ให้เรื่อย ๆ จนกระทั่งเป็น 3.0 ตัวเต็ม และอัพเกรด minor release ไปเรื่อย ๆ แต่นั่นก็ใช้เวลา อย่างเร็วก็รอรุ่น 3.0pre ซึ่งคงดีกว่านี้พอสมควร แต่ถ้าไม่ไหวจริง ๆ ก็ให้ติดตั้ง firefox-2 ใช้งานไปก่อนได้ ซึ่งเสถียรดีมาก ๆ<br /></li><li><strong>Network Manager 0.6.6</strong> ผมเจอปัญหาอันหนึ่งคือ ถ้าต่อเน็ตด้วย ppp ผ่านโทรศัพท์มือถือที่มี EDGE ไม่ว่าจะหมุนเองด้วยคำสั่ง pppd หรือผ่าน network manager applet สถานะของ network จะยังแสดงเป็น offline อยู่ ซึ่งคุณสมบัติหนึ่งของ network manager คือมันใช้ dbus ในการสื่อสารกับโปรแกรมอื่น ๆ ได้ ปัญหาคือ Firefox 3.0 ดันฉลาดเกิน ขอเช็คสถานะเน็ตเวิร์คกับ network manager ผ่านทาง dbus ทุกครั้งที่เปิดโปรแกรม ถ้าเน็ตเวิร์คไม่พร้อม มันจะปรับไปโหมด offline ให้อัตโนมัติ ทีนี้พอใช้ ppp ต่อเน็ต ก็ต้องคอยยกเลิก offline ทุกครั้งไป<br />ปัญหานี้ Firefox ไม่รับว่าเป็นบั๊ก แต่โยนไปที่ network manager แทน ซึ่งการขยายขอบเขตการจัดการเน็ตเวิร์คไปถึง ppp นั้น จะอยู่ในแผนของรุ่น 0.7 ซึ่งก็ออกล่าช้าเช่นกัน คนพัฒนาอยู่ Red Hat ซึ่งจะออกมาให้ใช้ทัน Fedora 9 แต่กลับไม่ทันใช้ใน Hardy<br />ทางออก มีวิธีเลี่ยงปัญหา โดยยกเลิกการ roaming การใช้ Lan แบบสาย แล้วตั้งให้ใช้ Lan แบบ manual ด้วย dhcp จะทำให้ network manager ไม่มีสถานะ offline อีกต่อไป (ผมใช้วิธีนี้อยู่) ส่วน network manager 0.7 จะไม่ถูกอัพเดทใน Hardy แต่คนดูแลแพกเกจรับรองว่า เมื่อรุ่น 0.7 ออก จะเตรียมไว้ให้ใช้ใน backports</li><li><strong>F-Spot</strong> ถูกใช้เป็นโปรแกรมหลักสำหรับจัดการรูปภาพในเครื่อง f-spot มีคุณสมบัติเด่น ๆ เรื่องการอัพโหลดรูปภาพไปยังบริการเก็บภาพบนอินเทอร์เน็ตหลายตัวเช่น flickr, picasaweb, gallery และอื่น ๆ อีก จำไม่ได้ละ ในด้านการใช้งานนั้น ดูจงใจให้เหมือน iPhotos ของ Mac ซึ่งก็ทำได้ดีทีเดียว แต่ปัญหาคือยังขาดคุณสมบัติอื่น ๆ ที่เคยมีใน gthumb ที่เป็นตัวหลักใน Ubuntu รุ่นก่อน ๆ เช่นการบราวซ์ดูภาพในโฟลเดอร์ที่ยังดูอืด ๆ แถมมันไม่เรียงลำดับมาให้ และเลือกให้เรียงไม่ได้ด้วย ทำให้เกือบจะไร้ประโยชน์ไปเลยทีเดียว ไม่มีการ prefetch ภาพต่อไปไว้ล่วงหน้า ทำให้ตอนดูภาพต่อไปต้องรอมันประมวลผลสักแป๊บนึงก่อน<br />ทางออก ติดตั้งโปรแกรมตัวเก่งอย่าง gthumb หรือ gqview เถอะครับ สำหรับคนที่ชอบจัดภาพไว้ใน directory ด้วยตัวเองอย่างผม แล้วจะพบว่ามันสะดวกขึ้นเยอะเลย โดยส่วนตัวชอบ gqview มากกว่า เพราะเล็กและเร็วดี</li></ol><br />kamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com0tag:blogger.com,1999:blog-6885844.post-64743418965434903122008-04-17T05:54:00.000+07:002011-07-27T12:26:42.285+07:00Suspend/Hibernate with ATI proprietary driver on Ubuntu Gutsy/Hardyแล็ปท็อปที่ใช้อยู่นี้ ใช้ชิปแสดงผลเป็น ATI Radeon Xpress 200M ตอนที่ใช้ Ubuntu 7.04 (Feisty) นั้น สามารถ suspend/hibernate ได้ทันทีโดยไม่ต้องตั้งค่าอะไรเพิ่มเติม น่าประทับใจมาก แต่ไปเสียตรงเรื่อง driver ของ wireless ที่ผมใช้นั้นยังไม่เก่ง ตอนนั้นต้องหันไปพึ่ง wifi-radar แทน NetworkManager (<a href="http://kamthorn.org/2007/04/21/feisty-%e0%b8%81%e0%b8%b1%e0%b8%9a%e0%b8%9b%e0%b8%b1%e0%b8%8d%e0%b8%ab%e0%b8%b2%e0%b8%81%e0%b8%b2%e0%b8%a3%e0%b8%95%e0%b9%88%e0%b8%ad-wireless">บล็อกเก่า</a>) พออัพเกรดมาเป็น 7.10 (Gutsy) ปัญหาเรื่อง wireless + NetworkManager หมดไป แต่มาตายเอาตรง suspend/hibernate กลับไม่ทำงาน คือจริง ๆ แล้วมัน suspend/hibernate ได้ แต่พอเรียกกลับมาก มันค้างไปเลย หน้าจอดำสนิท ต้องปิดแล้วเปิดใหม่เท่านั้น<br /><br />ตอนแรกไม่รู้วิธีแก้ เลยต้องปิดฟังก์ชันการ supend และ hibernate ไป และต้องปิดเครื่องทุกครั้งที่ไม่ได้ใช้งาน ซึ่งไม่สะดวกเอามาก ๆ<br /><br />เมื่อราว ๆ 15 ก.พ. 51 เลยลองหาวิธีแก้ดูซักตั้ง มั่ว ๆ ดูใน /etc/default/acpi-support แล้วสำเร็จ แต่ยังไม่ชัดเจนนักว่าเพราะคอนฟิกบรรทัดไหนแน่ หรือรวม ๆ กัน<br /><br />คราวนี้มาติดตั้ง 8.04 (Hardy) ก็พบปัญหาเดิมอีก วันนี้เลยมาลองค้นหาข้อมูลในเน็ตดูอีกที พบอันนี้เข้า <a href="http://wiki.cchtml.com/index.php/Ubuntu_Gutsy_Installation_Guide#Suspend.2FHibernation_work_with_7.12">http://wiki.cchtml.com/index.php/Ubuntu_Gutsy_Installation_Guide#Suspend.2FHibernation_work_with_7.12</a> ตรง ๆ เลย ทำตามแล้วได้ทันที สรุปว่าให้แก้แฟ้ม /etc/default/acpi-support ดังนี้<br /><p></p><pre>SAVE_VBE_STATE=false<br/>POST_VIDEO=false </pre><p>ซึ่งเดิมมันเป็น true ทั้งคู่ แล้ว reboot เครื่อง หรือ <code>sudo /etc/init.d/acpi-support restart</code> ต่อไปก็ใช้ได้เลย</p><p>สำหรับผู้ที่ใช้ Gutsy ต้องติดตั้ง radeontool เพิ่มด้วยนะครับ ส่วนใน Hardy นั้นติดตั้งมาพร้อมแล้ว<br /></p><p><br /></p>kamthornhttp://www.blogger.com/profile/09690729309562343399noreply@blogger.com1