หน้าเว็บ

วันอาทิตย์ที่ 7 มีนาคม พ.ศ. 2553

Google มีผล Real-Time Search จาก Twitter


วันนี้บังเอิญลองค้นคำว่า webos บน google.com ดูแล้วปรากฏว่าเจอผลลัพธ์การค้นหาที่มาจาก twitter ติดมาด้วย เลยขอบันทึกเก็บไว้หน่อย

เพิ่มเติม: ไปลองอ่านจากข่าวต่างๆพบว่ามันมีมานานแลว(ประมาณเดือนธันวาปีก่อน) สามารถเลือกให้แสดงได้โดยเลือกที่ Show options แล้วใต้ Any time ให้เลือก Latest แต่ว่ายังไม่รู้สาเหตุว่าทำไมบางครั้งมันไม่ต้องเลือกก็ขึ้นมาในผลลัพธ์เลยและ update อัตโนมัติด้วย (ถ้าใน Show options จะแสดงแบบ static)


วันพฤหัสบดีที่ 4 มีนาคม พ.ศ. 2553

แก้ค่า auto_increment ใน MySQL

บางครั้งในฐานข้อมูลที่มีการ set ให้มี field ที่เป็น auto_increment แต่บังเอิญเกิดเหตุการณ์ที่เราต้องไปลบ record สุดท้าย เช่น ถ้าค่าวิ่ง 1,2,3,4,5 แล้วเราลบ 5 ออก พอเราใส่อันใหม่เข้าไปมันจะยังนับต่อเนื่องจนกลายเป็น 1,2,3,4,6 ซึ่งเราอยากให้มันเริ่มนับต่อที่ 5 ให้เราแก้ไขโดยใช้คำสั่งดังนี้
ALTER TABLE ชื่อตาราง AUTO_INCREMENT=5
ถ้าต้องการให้เป็นค่าอื่นก็เปลี่ยนเอาตรงตัวเลขหลัง AUTO_INCREMENT= นั่นล่ะครับ

วันพุธที่ 3 มีนาคม พ.ศ. 2553

ความแตกต่างของ struct กับ typedef struct

ในภาษา C นั้นการประกาศ struct เพื่อสร้างประเภทข้อมูลชนิดใหม่โดยทำการนำหลายๆประเภทข้อมูลมาจัดกลุ่มเป็นอันเดียว ซึ่งคล้ายๆกับการสร้าง class ในภาษาแบบ OO(Object Oriented) (แต่มีแค่โครงสร้างข้อมูล ไม่มีคำสั่งสำหรับเรียกใช้)

ซึ่งการประกาศ struct ที่เห็นกันบ่อยๆก็คือ
(1)
struct ABC {
...
};


กับ (2)
typedef struct {
...
} ABC;


และ (3)
typedef struct ABC {
...
} ABC;


ที่สงสัยกันคือแต่ละแบบนั้นแตกต่างกันยังไง? เหตุผลลึกๆเดี๋ยวอธิบายไว้ด้านหลัง เริ่มจากดูวิธีการประกาศใช้ก่อน

ถ้าเกิดเราประกาศ ABC โดยใช้รูปแบบที่ (1) และถ้าเราจะประกาศตัวแปรประเภทนี้ขึ้นมา เราต้องประกาศว่า
struct ABC v;
ถึงจะเรียกใช้งานได้

ถ้าเป็นกรณีที่ (2) ล่ะก็เราจะสามารถประกาศตัวแปรโดยเชียนเพียงแค่
ABC v;

แต่ว่าการประกาศในรูปแบบที่ (1) จะดีกว่าในรูปแบบที่ (2) ก็คือเราสามารถประกาศโครงสร้างล่วงหน้าโดยยังไม่ต้องใส่รายละเอียดของโครงสร้างข้อมูลได้ ซึ่งเรียกว่าการทำ Forward-Declaration เช่น
struct ABC x;
...
struct ABC {
...
};

ในขณะที่แบบที่ (2) ทำไม่ได้

ดังนั้นการที่จะทำให้แบบที่ (2) ทำ Forward-Declaration ได้บ้าง จึงพัฒนามาเป็นการประกาศในแบบที่ (3) ซึ่งเป็นการรวมข้อดีของแบบที่ (1) กับ (2) นั่นคือ เวลาประกาศตัวแปรก็จะเขียนแค่
ABC x;
และสามารถทำ Forward-Declaration ได้(แต่ในส่วน Forward-Declaration ยังต้องประกาศเป็น struct ABC อยู่) เช่น
struct ABC x;
...
typedef struct ABC {
...
} ABC;
// หลังจากนี้จึงเรียกแค่ ABC ได้
ABC y;


ส่วนเหตุผลลึกๆก็คือในภาษา C นั้นจะมีการแบ่ง namespace ของ type ออกเป็น 2 แบบ คือ tag namespace กับ typedef namespace ซึ่งการประกาศแบบที่ (1) นั้นจะเป็นการนำคำว่า ABC เข้าไปอยู่ใน tag namespace เพื่อใช้ในการอ้างถึงของการประกาศตัวแปรแบบ struct เพียงเท่านั้น ดังนั้นเวลาประกาศตัวแปรจึงต้องใช้ struct ABC x; แต่ในขณะที่แบบที่ (2) นั้นเป็นการนำคำว่า ABC เข้าไปอยู่ใน typedef namespace ซึ่ง typedef namespace นี้ให้มองว่าคล้ายการสร้าง map เพื่อจับว่าถ้าเจอคำว่า ABC ให้แทนด้วยคำว่า struct ABC ไปซะ ดังนั้นจึงสามารถประกาศสั้นๆได้ว่า ABC x; ส่วนการประกาศแบบที่ (3) ก็คือการนำคำ ABC ไปใส่ไว้ในทั้ง tag namespace และ typedef namespace เลย

ส่วนการทำ Forward-Declaration นั้นคือต้องมีประเภทตัวแปรที่จะประกาศอยู่ใน tag namespace เสียก่อนจึงจะสามารถทำได้

หลักการของ tag namespace นั้นจะใช้ได้กับทั้ง struct, enum, union (เพราะพวกนี้นับว่าอยู่ใน tag namespace)

แต่ถ้าเป็นภาษา C++ แล้ว แบบที่ (1), (2), (3) ไม่แตกต่างกัน เนื่องจาก การประกาศ struct/enum/union/class ใน C++ นั้นจะเหมือนการถูกทำ typedef ไปเรียบร้อย

อ้างอิง
http://stackoverflow.com/questions/612328/difference-between-struct-and-typedef-struct-in-c
http://www.embedded.com/story/OEG20020926S0059

วันพุธที่ 2 ธันวาคม พ.ศ. 2552

shell script with floating point

มีรุ่นน้องในแลบถามผมว่า อยากจะทำ for loop ให้ มันแสดงค่าตั้งแต่ 0.01 ถึง 0.20 ทำยังไงดี? ซึ่งน้องเค้าตรง for loop ก็ทำเป็น integer 1 ถึง 20 แต่ว่า ตอนแสดงจะนำมาหารด้วย 100

ปัญหาอย่างหนึ่งของ shell script คือทำ floating point arithmetic operation ดื้อๆไม่ได้ ดังนั้นมันจึงเอามาหาร 100 เกิดเป็นทศนิยมไม่ได้

วิธีแก้ปัญหาก็แน่นอนอาจจะเขียน script python perl c ฯลฯ อะไรก็ได้ในการแก้ปัญหานี้
แต่ว่าผมพบอีกวิธีนึงซึ่งก็ค่อนข้าง work และถูกออกแบบมาทำเพื่อทำ arithmetic operation อย่างเดียวเลย ก็คือการใช้ bc หรือ bash calculator

ซึ่งจริงๆก็เขียนคล้ายๆพวก script ต่างๆนั่นแหล่ะ เช่นถ้าต้องการจะทำผลลัพธ์ for loop ที่กล่าวไว้ข้างต้นก็ทำได้โดยจับมายำกับ shell script แบบนี้

for ((i=1;i<20;i+=1)) do printf "0%s\n" $(echo "scale=2; $i/100" | bc); done

จริงๆแล้วจะยัดพวก for อะไร เข้าไปใน bc ทั้งหมดเลยก็ได้ แต่อันนี้เพียงต้องการแสดงให้เห็นว่าถ้ามี shell script อยู่แล้ว และต้องการทำ floating point arithmetic operation แค่บางจุดจะต้องทำอย่างไรเท่านั้น

ระบบที่ทดสอบ
OS: Ubuntu 9.04

วันอังคารที่ 27 ตุลาคม พ.ศ. 2552

ดาวน์โหลดทั้งเวบเพื่อทำ Offline Browsing บน linux

ในกรณีที่เราต้องการดาวน์โหลดเวบทั้งเวบมาเก็บไว้ในเครื่องเราเพื่อเปิดดูภายหลัง หรือ Offline Browsing นั้น แท้จริงแล้วไม่ต้องใช้โปรแกรมเพิ่มเติมอะไรมากเลยครับ เพียงแค่ wget ก็สามารถช่วยเราทำแบบนั้นได้ ด้วยคำสั่งดังต่อไปนี้ครับ

wget -H -r --level=1 -k -p http://yoururl.com

โดย -H หมายถึง span host คือเอา link ที่อยู่โฮสต์อื่นมาด้วย
-r หมายถึง recursive คือเอาลิงค์ที่อยู่ในระดับที่ลึกลงไปมาด้วย
--level บอกว่าจะเอาลึกลงไปกี่ชั้น
-k คือสั่งให้แปลงลิงค์ที่ชี้ไปยังโฮสต์อื่น(โฮสต์จริง) เป็นลิงค์ของโฮสต์อื่นแต่ถูกดูดมาอยู่ในเครื่องเราแล้ว
-p คือ ขอทุกๆส่วนประกอบของหน้าเวบนั้น เช่น รูปภาพ เป็นต้น

ที่มา
http://lifehacker.com/software/downloads/geek-to-live--mastering-wget-161202.php

ระบบที่ทดสอบ
OS: Ubuntu 9.04

วันอาทิตย์ที่ 27 กันยายน พ.ศ. 2552

Run Command as Other User

วิธีการที่จะสั่ง run คำสั่งใดๆ แต่ให้เสมือนว่าเป็น user คนอื่นเป็นคนสั่งทำได้โดยใช้คำสั่งดังนี้
su - username -c "commandname"
โดยหลังเครื่องหมาย "-" ตัวแรก ให้ตามด้วยเว้นวรรค ก่อนแล้วค่อยเป็น username แต่ตรง "-c" พิมพ์ติดกัน
หรือใช้คำสั่ง
sudo -u username commandname
ก็ได้เช่นเดียวกัน
สามารถทดสอบโดยเห็นผลชัดๆก็คือคำสั่ง id ซึ่งจะแสดงค่าข้อมูลของ user ที่สั่งคำสั่งขึ้นมา ดังนี้

ถ้าเป็นผู้ใช้ที่เป็น admin สั่งคำสั่ง id จะได้ผลลัพธ์
uid=1000(supasate) gid=1000(supasate) groups=4(adm),..........
เป็นต้น

แต่ถ้าต้องการให้สั่งคำสั่งในฐานะ user ธรรมดาที่ชื่อ ping
su - ping -c "id"
หรือ
sudo -u ping id
จะได้ผลลัพทธ์
uid=1001(ping) gid=1001(ping) groups=1001(ping)
เป็นต้น

ระบบที่ทดสอบ
OS:
Ubuntu 9.04 Server

ที่มา
http://ubuntuforums.org/showthread.php?t=879283

สร้าง password ป้องกัน grub

ถ้าเกิดไม่ต้องการให้ใครมา boot เครื่องเรา (ป้องกันการ boot ไม่ใช่ป้องกันการ login) สามารถป้องกันได้โดยใส่ password ไว้ที่ grub เลย ซึ่งประโยชน์หลักๆก็มีด้วย 3 ประการ
1. ป้องกันการเข้าถึง Single-user mode เช่น การเข้า recovery console ซึ่งถ้าเข้ามาในโหมดนี้จะทำการ log in เป็น root ทันทีโดยไม่ต้องใส่ password root
2. ป้องกันการเข้าถึง grub console เพราะถ้าเครื่อง boot ด้วย grub แล้ว ผู้ไม่หวังดีสามารถดึงข้อมูลการตั้งค่าของ grub หรือทำการแก้ไขค่าด้วย grub editor interface ได้
3. ป้องกันการเข้าถึง OS ที่ไม่มีที่การป้องกันไม่ค่อยดี เช่น เข้าได้โดยไม่ต้องใส่ password (เช่น DOS) ในกรณีที่เครื่องเราทำ dual-boot หรือลงหลายๆ OS ไว้ในเครื่องเดียว

วิธีการทำ
มีดังนี้
1. ใช้คำสั่ง grub-md5-crypt เพื่อ generate ค่า hash ของ password ออกมา
2. แก้ไขไฟล์ /boot/grup/menu.lst โดยให้เติมค่า password --md5 ค่าแฮช ไว้ที่บรรทัดสุดท้ายของแต่ละ OS ที่ต้องการจะป้องกัน เช่น

title Ubuntu, kernel 2.6.8.1-2-386 (recovery mode)
root (hd1,2)
kernel /boot/vmlinuz-2.6.8.1-2-386 root=/dev/hdb3 ro single
initrd /boot/initrd.img-2.6.8.1-2-386
password --md5 $1$w7Epf0$vX6rxpozznLAVxZGkcFcs

แล้วลองทดสอบโดยการ reboot เข้า grub เป็นอันเสร็จ

ข้อควรระวัง อย่าใส่ค่า hash value ผิด

ระบบที่ทดสอบ
OS: Ubuntu 9.04 Server

ที่มา
http://ubuntuforums.org/showthread.php?t=7353
http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/en-US/Security_Guide/s2-wstation-bootloader.html