<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SpaLinux.com</title>
	<atom:link href="http://spalinux.com/feed" rel="self" type="application/rss+xml" />
	<link>http://spalinux.com</link>
	<description>Resources for Relaxing Linux System Administrators</description>
	<lastBuildDate>Sun, 07 Mar 2010 16:03:00 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>เพิ่มดิสก์ใหม่บน Solaris 10</title>
		<link>http://spalinux.com/2010/03/add_new_disk_on_solaris_10</link>
		<comments>http://spalinux.com/2010/03/add_new_disk_on_solaris_10#comments</comments>
		<pubDate>Sun, 07 Mar 2010 16:02:40 +0000</pubDate>
		<dc:creator>editor</dc:creator>
				<category><![CDATA[Disk]]></category>
		<category><![CDATA[Filesystem]]></category>
		<category><![CDATA[Solaris]]></category>
		<category><![CDATA[solaris 10]]></category>

		<guid isPermaLink="false">http://spalinux.com/?p=1100</guid>
		<description><![CDATA[เช่นเดียวกับระบบปฏิบัติการ OS อื่นๆ เมื่อมีการเพิ่มดิสก์ก้อนใหม่เข้าไปในเครื่องที่ติดตั้ง Solaris 10 ต้องมีกระบวนการ หรือต้องรันคำสั่งก่อนที่จะเริ่มใช้ดิสก์ก้อนใหม่ได้

ในบทความนี้ทดสอบการเพิ่มดิสก์ก้อนใหม่ 1 ก้อน บน Solaris 10 (x86)
ใช้คำสั่ง format เพื่อดูว่า Solaris มองเห็นดิสก์อะไรบ้าง
# format
Searching for disks...done
AVAILABLE DISK SELECTIONS:
       0. c1t0d0 &#60;DEFAULT cyl 4866 alt 2 hd 255 sec 63&#62;
          /pci@0,0/pci1000,30@10/sd@0,0
       1. c1t1d0 &#60;DEFAULT cyl 4867 alt 2 hd 255 sec 63&#62;
          /pci@0,0/pci1000,30@10/sd@1,0
Specify disk (enter its number):
ดิสก์ก้อนใหม่ที่เพิ่มเข้ามาคือดิสก์หมายเลข 1 &#8220;c1t1d0&#8243;
พิมพ์หมายเลขของดิสก์แล้วกด [Enter] เพื่อเข้าสู่โหมดจัดการของดิสก์ก้อนที่ระบุ
Specify [...]]]></description>
			<content:encoded><![CDATA[<p>เช่นเดียวกับระบบปฏิบัติการ OS อื่นๆ เมื่อมีการเพิ่มดิสก์ก้อนใหม่เข้าไปในเครื่องที่ติดตั้ง Solaris 10 ต้องมีกระบวนการ หรือต้องรันคำสั่งก่อนที่จะเริ่มใช้ดิสก์ก้อนใหม่ได้</p>
<p><span id="more-1100"></span></p>
<p>ในบทความนี้ทดสอบการเพิ่มดิสก์ก้อนใหม่ 1 ก้อน บน Solaris 10 (x86)</p>
<p>ใช้คำสั่ง format เพื่อดูว่า Solaris มองเห็นดิสก์อะไรบ้าง</p>
<pre># <strong>format</strong>
Searching for disks...done</pre>
<pre>AVAILABLE DISK SELECTIONS:
       0. c1t0d0 &lt;DEFAULT cyl 4866 alt 2 hd 255 sec 63&gt;
          <a>/pci@0,0/pci1000,30@10/sd@0,0</a>
       <span style="color: #0000ff;"><strong>1. c1t1d0</strong></span> &lt;DEFAULT cyl 4867 alt 2 hd 255 sec 63&gt;
          <a>/pci@0,0/pci1000,30@10/sd@1,0</a>
Specify disk (enter its number):</pre>
<p>ดิสก์ก้อนใหม่ที่เพิ่มเข้ามาคือดิสก์หมายเลข 1 &#8220;c1t1d0&#8243;</p>
<p>พิมพ์หมายเลขของดิสก์แล้วกด [Enter] เพื่อเข้าสู่โหมดจัดการของดิสก์ก้อนที่ระบุ</p>
<pre>Specify disk (enter its number): <strong>1</strong>
selecting c1t1d0
[disk formatted]</pre>
<pre>FORMAT MENU:
        disk       - select a disk
        type       - select (define) a disk type
        partition  - select (define) a partition table
        current    - describe the current disk
        format     - format and analyze the disk
        fdisk      - run the fdisk program
        repair     - repair a defective sector
        label      - write label to the disk
        analyze    - surface analysis
        defect     - defect list management
        backup     - search for backup labels
        verify     - read and display labels
        save       - save new disk/partition definitions
        inquiry    - show vendor, product and revision
        volname    - set 8-character volume name
        !&lt;cmd&gt;     - execute &lt;cmd&gt;, then return
        quit</pre>
<p>พิมพ์คำสั่ง partition เพื่อเข้าสู่โหมดการแบ่ง partition</p>
<pre>format&gt; <strong>partition</strong>
<span style="color: #ff0000;">WARNING - This disk may be in use by an application that has
          modified the fdisk table. Ensure that this disk is
          not currently in use before proceeding to use fdisk.</span></pre>
<p>หากเจอข้อความ WARNING แบบด้านบน ให้พิมพ์คำสั่ง fdisk เพื่อแก้ไข</p>
<pre>format&gt; <strong>fdisk</strong>
No fdisk table exists. The default partition for the disk is:</pre>
<pre>  a 100% "SOLARIS System" partition</pre>
<pre>Type "y" to accept the default partition,  otherwise type "n" to edit the
 partition table.
<strong>y</strong>
format&gt;</pre>
<p>พิมพ์คำสั่ง partition อีกครั้ง</p>
<pre>format&gt; <strong>partition</strong></pre>
<pre>PARTITION MENU:
        0      - change `0' partition
        1      - change `1' partition
        2      - change `2' partition
        3      - change `3' partition
        4      - change `4' partition
        5      - change `5' partition
        6      - change `6' partition
        7      - change `7' partition
        select - select a predefined table
        modify - modify a predefined partition table
        name   - name the current table
        print  - display the current table
        label  - write partition map and label to the disk
        !&lt;cmd&gt; - execute &lt;cmd&gt;, then return
        quit
partition&gt;</pre>
<p>พิมพ์คำสั่ง print เพื่อแสดงการแบ่ง partition</p>
<pre>partition&gt; <strong>print</strong>
Current partition table (original):
Total disk cylinders available: 4866 + 2 (reserved cylinders)</pre>
<pre>Part      Tag    Flag     Cylinders        Size            Blocks
<span style="color: #0000ff;">  0 unassigned    wm       0               0         (0/0/0)           0
</span>  1 unassigned    wm       0               0         (0/0/0)           0
  2     backup    wu       0 - 4865       37.28GB    (4866/0/0) 78172290
  3 unassigned    wm       0               0         (0/0/0)           0
  4 unassigned    wm       0               0         (0/0/0)           0
  5 unassigned    wm       0               0         (0/0/0)           0
  6 unassigned    wm       0               0         (0/0/0)           0
  7 unassigned    wm       0               0         (0/0/0)           0
  8       boot    wu       0 -    0        7.84MB    (1/0/0)       16065
  9 unassigned    wm       0               0         (0/0/0)           0</pre>
<pre>partition&gt;</pre>
<p>เริ่มต้น ทดลองสร้าง partition 0 มีขนาด 10 GB</p>
<pre>partition&gt; <strong>0</strong>
Part      Tag    Flag     Cylinders        Size            Blocks
  0 unassigned    wm       0               0         (0/0/0)           0</pre>
<pre>Enter partition id tag[unassigned]:
Enter partition permission flags[wm]:
Enter new starting cyl[0]:
Enter partition size[0b, 0c, 0e, 0.00mb, 0.00gb]: <strong>10gb</strong></pre>
<p>ใช้คำสั่ง print เพื่อแสดง partition</p>
<pre>partition&gt; <strong>print</strong>
Current partition table (unnamed):
Total disk cylinders available: 4866 + 2 (reserved cylinders)</pre>
<pre>Part      Tag    Flag     Cylinders        Size            Blocks
<span style="color: #0000ff;">  0 unassigned    wm       0 - 1305       10.00GB    (1306/0/0) 20980890
</span>  1 unassigned    wm       0               0         (0/0/0)           0
  2     backup    wu       0 - 4865       37.28GB    (4866/0/0) 78172290
  3 unassigned    wm       0               0         (0/0/0)           0
  4 unassigned    wm       0               0         (0/0/0)           0
  5 unassigned    wm       0               0         (0/0/0)           0
  6 unassigned    wm       0               0         (0/0/0)           0
  7 unassigned    wm       0               0         (0/0/0)           0
  8       boot    wu       0 -    0        7.84MB    (1/0/0)       16065
  9 unassigned    wm       0               0         (0/0/0)           0</pre>
<p>หลังจากแก้ไข partition พิมพ์คำสั่ง label เพื่อบันทึกข้อมูลลงดิสก์</p>
<pre>partition&gt; <strong>label</strong>
Ready to label disk, continue? <strong>y</strong></pre>
<pre>partition&gt; <strong>^D</strong></pre>
<p>กดปุ่ม [Ctrl]+[D] เพื่อออกจากคำสั่ง format</p>
<p>ใช้คำสั่ง newfs เพื่อสร้าง filesystem บน partition ที่เพิ่งสร้างขึ้น</p>
<p>หมายเหตุ ชื่อไฟล์ device ของดิสก์ c1t1d0 &#8211; partition 0 คือ /dev/rdsk/c1t1d0s0</p>
<pre># <strong>newfs /dev/rdsk/c1t1d0s0
</strong>newfs: construct a new file system /dev/rdsk/c1t1d0s0: (y/n)? y
Warning: 870 sector(s) in last cylinder unallocated
/dev/rdsk/c1t1d0s0:     20980890 sectors in 3415 cylinders of 48 tracks, 128 sectors
        10244.6MB in 214 cyl groups (16 c/g, 48.00MB/g, 5824 i/g)
super-block backups (for fsck -F ufs -o b=#) at:
 32, 98464, 196896, 295328, 393760, 492192, 590624, 689056, 787488, 885920,
 20055584, 20154016, 20252448, 20350880, 20449312, 20547744, 20646176,
 20744608, 20843040, 20941472</pre>
<p>แนะนำให้ใช้คำสั่ง fsck เพื่อตรวจสอบความถูกต้องของ filesystem ที่สร้างขึ้น ต้องไม่มีข้อความ error ใดๆ</p>
<pre># <strong>fsck -y /dev/rdsk/c1t1d0s0
</strong>** /dev/rdsk/c1t1d0s0
** Last Mounted on
** Phase 1 - Check Blocks and Sizes
** Phase 2 - Check Pathnames
** Phase 3a - Check Connectivity
** Phase 3b - Verify Shadows/ACLs
** Phase 4 - Check Reference Counts
** Phase 5 - Check Cylinder Groups
2 files, 9 used, 10331200 free (16 frags, 1291398 blocks, 0.0% fragmentation)</pre>
<p>สร้าง mount point สำหรับ partition ใหม่</p>
<pre># <strong>mkdir /mnt/new-disk0
</strong># <strong>mount /dev/rdsk/c1t1d0s0 /mnt/new-disk0
</strong><span style="color: #ff0000;">mount: /dev/rdsk/c1t1d0s0 not a block device</span></pre>
<p>สำหรับ Solaris เวลาใช้คำสั่ง newfs หรือ fsck ชื่อ device ที่ระบุคือ /dev/rdsk/&#8230; แต่เวลาใช้คำสั่ง mount ต้องระบุชื่อ device เป็น /dev/dsk/&#8230;</p>
<pre># <strong>mount /dev/dsk/c1t1d0s0 /mnt/new-disk0</strong></pre>
<p>ใช้คำสั่ง df เพื่อตรวจสอบ mount point</p>
<pre># <strong>df -h
</strong>Filesystem             size   used  avail capacity  Mounted on
/dev/dsk/c1t0d0s0       34G   3.7G    30G    11%    /
/devices                 0K     0K     0K     0%    /devices
ctfs                     0K     0K     0K     0%    /system/contract
proc                     0K     0K     0K     0%    /proc
mnttab                   0K     0K     0K     0%    /etc/mnttab
swap                   1.6G   932K   1.6G     1%    /etc/svc/volatile
objfs                    0K     0K     0K     0%    /system/object
sharefs                  0K     0K     0K     0%    /etc/dfs/sharetab
/usr/lib/libc/libc_hwcap1.so.1
                        34G   3.7G    30G    11%    /lib/libc.so.1
fd                       0K     0K     0K     0%    /dev/fd
swap                   1.6G     8K   1.6G     1%    /tmp
swap                   1.6G    20K   1.6G     1%    /var/run
/dev/dsk/c1t0d0s7      1.9G   210M   1.6G    12%    /export/home
<span style="color: #0000ff;">/dev/dsk/c1t1d0s0      9.9G    10M   9.7G     1%    /mnt/new-disk0</span></pre>
<p>หากใช้งาน partition ใหม่ได้ถูกต้องเรียบร้อยแล้ว ต้องเพิ่มคอนฟิกเข้าไปในไฟล์ /etc/vfstab เพื่อให้เวลาบู๊ตเครื่องใหม่ มีการ mount partition ใหม่นี้โดยอัตโมมัติ</p>
<pre># <strong>cat /etc/vfstab
</strong>#device         device          mount           FS      fsck    mount   mount
#to mount       to fsck         point           type    pass    at boot options
#
fd      -       /dev/fd fd      -       no      -
/proc   -       /proc   proc    -       no      -
/dev/dsk/c1t0d0s1       -       -       swap    -       no      -
/dev/dsk/c1t0d0s0       /dev/rdsk/c1t0d0s0      /       ufs     1       no      -
/dev/dsk/c1t0d0s7       /dev/rdsk/c1t0d0s7      /export/home    ufs     2       yes     -
/devices        -       /devices        devfs   -       no      -
sharefs -       /etc/dfs/sharetab       sharefs -       no      -
ctfs    -       /system/contract        ctfs    -       no      -
objfs   -       /system/object  objfs   -       no      -
swap    -       /tmp    tmpfs   -       yes     -
# new disk
<span style="color: #0000ff;">/dev/dsk/c1t1d0s0       /dev/rdsk/c1t1d0s0      /mnt/new-disk0  ufs     2       yes     -</span></pre>
]]></content:encoded>
			<wfw:commentRss>http://spalinux.com/2010/03/add_new_disk_on_solaris_10/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ขนาดหน่วยความจำกับการติดตั้ง Solaris 10_u8 x86</title>
		<link>http://spalinux.com/2010/03/memory_size_with_solaris_10_u8_x86_installation</link>
		<comments>http://spalinux.com/2010/03/memory_size_with_solaris_10_u8_x86_installation#comments</comments>
		<pubDate>Sat, 06 Mar 2010 07:15:25 +0000</pubDate>
		<dc:creator>editor</dc:creator>
				<category><![CDATA[Hardware]]></category>
		<category><![CDATA[Solaris]]></category>
		<category><![CDATA[solaris 10]]></category>

		<guid isPermaLink="false">http://spalinux.com/?p=1092</guid>
		<description><![CDATA[ช่วงนี้รับงานที่ต้องใช้ Solaris 10 เป็นหลัก เลยติดตั้ง Solaris ใน VMware Server เพื่อไว้เป็นเครื่องทดสอบคำสั่ง และโปรแกรมต่างๆ
บทความนี้ขอนำประสบการณ์มาแชร์ให้กัน เผื่อเป็นประโยชน์สำหรับผู้ติดปัญหาการติดตั้ง Solaris 10 x86 เหมือนผู้เขียน

ในที่นี้ใช้ไฟล์ iso (sol-10-u8-ga-x86-dvd.iso) จากเว็บไซต์ sun.com เพื่อติดตั้งบน VMware Server
คอนฟิก guest ที่สร้างไว้ บน VMware Server เวอร์ชั่น 1.0.10 คือ
Guest Operating System: Solaris 10 64-bit
Memory 512 MB
Disk 37.3 GB
พยายามติดตั้งอยู่นานก็ไม่สามารถติดตั้งได้ ขึ้น error
SunOS Release 5.10 Version Generic_141445-09 32-bit
Copyright 1983-2009 Sun Microsystems, Inc.  All rights reserved.
Use is [...]]]></description>
			<content:encoded><![CDATA[<p>ช่วงนี้รับงานที่ต้องใช้ Solaris 10 เป็นหลัก เลยติดตั้ง Solaris ใน VMware Server เพื่อไว้เป็นเครื่องทดสอบคำสั่ง และโปรแกรมต่างๆ</p>
<p>บทความนี้ขอนำประสบการณ์มาแชร์ให้กัน เผื่อเป็นประโยชน์สำหรับผู้ติดปัญหาการติดตั้ง Solaris 10 x86 เหมือนผู้เขียน</p>
<p><span id="more-1092"></span></p>
<p>ในที่นี้ใช้ไฟล์ iso (sol-10-u8-ga-x86-dvd.iso) จากเว็บไซต์ sun.com เพื่อติดตั้งบน VMware Server</p>
<p>คอนฟิก guest ที่สร้างไว้ บน VMware Server เวอร์ชั่น 1.0.10 คือ</p>
<p>Guest Operating System: Solaris 10 64-bit<br />
Memory 512 MB<br />
Disk 37.3 GB</p>
<p>พยายามติดตั้งอยู่นานก็ไม่สามารถติดตั้งได้ ขึ้น error</p>
<pre>SunOS Release 5.10 Version Generic_141445-09 32-bit
Copyright 1983-2009 Sun Microsystems, Inc.  All rights reserved.
Use is subject to license terms.</pre>
<pre><span style="color: #ff0000;">panic[cpu0]/thread=fec20160: page_unlock: page fe2b57d0 is not locked.</span></pre>
<p><a href="http://spalinux.com/wp-content/uploads/2010/03/01-Install_Solaris_10_x86_panic_with_memory_512MB.png"><img title="Install Solaris 10 x86 - panic with memory 512MB" src="http://spalinux.com/wp-content/uploads/2010/03/01-Install_Solaris_10_x86_panic_with_memory_512MB.png" alt="" width="720" height="400" /></a></p>
<p>หลังจากค้นหาข้อมูลอยู่นาน ก็พบต้นตอของปัญหาจากเว็บไซต์ <a href="http://forums.sun.com/thread.jspa?threadID=5411801" target="_blank">Installation &#8211; Solaris 10 Installation error on Thinkpad A20m &#8211; Please help!!!!!!! PLEASE!<br />
</a></p>
<blockquote><p>S10U8 cannot hit a 512Mb memory system and I suspect you are there. In Parallels you can just up the memory slightly. At least in virtual box 512</p>
<p>will give the same error while 609mb does not.</p></blockquote>
<p>ทดลองเปลี่ยนคอนฟิกของ memory เป็น 768 MB ผลเป็นว่าสามารถติดตั้ง Solaris 10 ได้ แต่สังเกตว่าน่าจะเป็นการติดตั้ง Solaris 10 แบบ 32-bit</p>
<pre>SunOS Release 5.10 Version Generic_141445-09 <span style="color: #0000ff;">32-bit</span></pre>
<p><a href="http://spalinux.com/wp-content/uploads/2010/03/02-Install_Solaris_10_x86_32-bit_with_memory_768MB.png"><img title="Install Solaris 10 x86 32-bit with memory 768MB" src="http://spalinux.com/wp-content/uploads/2010/03/02-Install_Solaris_10_x86_32-bit_with_memory_768MB.png" alt="" width="720" height="400" /></a></p>
<p>ทดลองเพิ่มขนาด memory เป็น 1024 MB ผลที่ได้ จะเป็นการติดตั้ง Solaris 10 แบบ 64-bit</p>
<pre>SunOS Release 5.10 Version Generic_141445-09 64-bit</pre>
<p><a href="http://spalinux.com/wp-content/uploads/2010/03/03-Install_Solaris_10_x86_64-bit_with_memory_1024MB.png"><img title="Install Solaris 10 x86 64-bit with memory 1024MB" src="http://spalinux.com/wp-content/uploads/2010/03/03-Install_Solaris_10_x86_64-bit_with_memory_1024MB.png" alt="" width="720" height="400" /></a></p>
<p>แต่ไม่ว่าจะคอนฟิกขนาด Memory 768 MB หรือ 1024 MB ตอนติดตั้ง สุดท้าย Solaris ที่ได้จะเป็นแบบ 64-bit</p>
<p>หมายเหตุ ไม่ได้ทดสอบบนเครื่อง PC จริงๆ ว่าได้ผลเหมือนกันหรือไม่ ลองกันดูนะครับ</p>
<h4>ข้อมูลอ้างอิง</h4>
<ul>
<li><a href="http://www.sun.com/software/solaris/get.jsp" target="_blank">Get Solaris 10</a></li>
<li><a href="http://forums.sun.com/thread.jspa?threadID=5411801" target="_blank">Installation &#8211; Solaris 10 Installation error on Thinkpad A20m &#8211; Please help!!!!!!! PLEASE!</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://spalinux.com/2010/03/memory_size_with_solaris_10_u8_x86_installation/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>รันโปรเซสเป็น user อื่น</title>
		<link>http://spalinux.com/2010/03/run_process_as_another_user</link>
		<comments>http://spalinux.com/2010/03/run_process_as_another_user#comments</comments>
		<pubDate>Sat, 06 Mar 2010 05:52:51 +0000</pubDate>
		<dc:creator>editor</dc:creator>
				<category><![CDATA[Authentication]]></category>
		<category><![CDATA[Linux Shell]]></category>
		<category><![CDATA[UNIX]]></category>
		<category><![CDATA[Users]]></category>
		<category><![CDATA[Utility]]></category>
		<category><![CDATA[unix process]]></category>

		<guid isPermaLink="false">http://spalinux.com/?p=1088</guid>
		<description><![CDATA[เป็นวิธีง่ายๆ เพื่อให้ผู้ใช้ root สามารถรันโปรเซสหรือโปรแกรมบน Linux/UNIX ภายใต้สิทธิหรือ permission ผู้ใช้ user อื่นบนเครื่องเดียวกัน
คำสั่งที่ใช้คือ su ตามด้วยออปชั่น &#8216;-c&#8217; รูปแบบการใช้คำสั่งคือ
# su - &#60;user_name&#62; -c "&#60;command&#62;"
ตัวอย่าง root รันคำสั่ง id ภายใต้สิทธิผู้ใช้ชื่อ user1
# su - user1 -c "id"
uid=501(user1) gid=100(users) groups=100(users)
ข้อมูลอ้างอิง

&#8217;su&#8217; man page

]]></description>
			<content:encoded><![CDATA[<p>เป็นวิธีง่ายๆ เพื่อให้ผู้ใช้ root สามารถรันโปรเซสหรือโปรแกรมบน Linux/UNIX ภายใต้สิทธิหรือ permission ผู้ใช้ user อื่นบนเครื่องเดียวกัน</p>
<p><span id="more-1088"></span>คำสั่งที่ใช้คือ su ตามด้วยออปชั่น &#8216;-c&#8217; รูปแบบการใช้คำสั่งคือ</p>
<pre># su - &lt;user_name&gt; -c "&lt;command&gt;"</pre>
<p>ตัวอย่าง root รันคำสั่ง id ภายใต้สิทธิผู้ใช้ชื่อ user1</p>
<pre># <strong>su - user1 -c "id"
</strong>uid=501(user1) gid=100(users) groups=100(users)</pre>
<h4>ข้อมูลอ้างอิง</h4>
<ul>
<li>&#8217;su&#8217; man page</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://spalinux.com/2010/03/run_process_as_another_user/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>คอนฟิก MySQL Replication</title>
		<link>http://spalinux.com/2010/02/configure_mysql_replication</link>
		<comments>http://spalinux.com/2010/02/configure_mysql_replication#comments</comments>
		<pubDate>Fri, 26 Feb 2010 09:20:58 +0000</pubDate>
		<dc:creator>editor</dc:creator>
				<category><![CDATA[Backup]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[mysql replication]]></category>

		<guid isPermaLink="false">http://spalinux.com/?p=1084</guid>
		<description><![CDATA[บทความนี้จะอธิบายวิธีการคอนฟิก Replication ของ MySQL เพื่อทำการ replicate ข้อมูลในฐานข้อมูล (database) จากเครื่องหลัก (Master) ไปยังเครื่องสำรอง (Slave) ได้
หลังจากที่คอนฟิก Replication ถูกต้องเรียบร้อย เมื่อมีการเปลี่ยนแปลงข้อมูลในฐานข้อมูลบนเครื่องหลัก (Master) ไม่ว่าจะเป็นการ INSERT, UPDATE, DELETE หรือ แก้ไข table การเปลี่ยนแปลงนี้จะถูกส่งต่อ (replicate) ไปยังเครื่องสำรอง (Slave) โดยอัตโนมัติ
การคอนฟิก Replication เป็นการป้องกันการเสียหาย ถ้าเครื่องหลักมีปัญหา ข้อมูลที่ถูกเก็บไว้ในเครื่องสำรอง ก็ยังสามารถใช้งานได้

ระบบทดสอบ
ตัวอย่างในบทความนี้ จะทดสอบบนเครื่องสองเครื่องที่ติดตั้ง CentOS 5.4 และ MySQL 5.1.43 เรียบร้อยแล้ว
เครื่อง Master

ip: 192.168.1.1
hostname: centos54-a

เครื่อง Slave

ip: 192.168.1.2
hostname: centos54-b

ตัวอย่างการใช้คำสั่ง rpm เพื่อตรวจสอบเวอร์ชั่นของ MySQL ที่ติดตั้ง
[root@centos54-a ~]# rpm -qa &#124; [...]]]></description>
			<content:encoded><![CDATA[<p>บทความนี้จะอธิบายวิธีการคอนฟิก Replication ของ MySQL เพื่อทำการ replicate ข้อมูลในฐานข้อมูล (database) จากเครื่องหลัก (Master) ไปยังเครื่องสำรอง (Slave) ได้</p>
<p>หลังจากที่คอนฟิก Replication ถูกต้องเรียบร้อย เมื่อมีการเปลี่ยนแปลงข้อมูลในฐานข้อมูลบนเครื่องหลัก (Master) ไม่ว่าจะเป็นการ INSERT, UPDATE, DELETE หรือ แก้ไข table การเปลี่ยนแปลงนี้จะถูกส่งต่อ (replicate) ไปยังเครื่องสำรอง (Slave) โดยอัตโนมัติ</p>
<p>การคอนฟิก Replication เป็นการป้องกันการเสียหาย ถ้าเครื่องหลักมีปัญหา ข้อมูลที่ถูกเก็บไว้ในเครื่องสำรอง ก็ยังสามารถใช้งานได้</p>
<p><span id="more-1084"></span></p>
<h4>ระบบทดสอบ</h4>
<p>ตัวอย่างในบทความนี้ จะทดสอบบนเครื่องสองเครื่องที่ติดตั้ง CentOS 5.4 และ MySQL 5.1.43 เรียบร้อยแล้ว</p>
<p>เครื่อง <strong>Master</strong></p>
<ul>
<li>ip: 192.168.1.1</li>
<li>hostname: centos54-a</li>
</ul>
<p>เครื่อง <strong>Slave</strong></p>
<ul>
<li>ip: 192.168.1.2</li>
<li>hostname: centos54-b</li>
</ul>
<p>ตัวอย่างการใช้คำสั่ง rpm เพื่อตรวจสอบเวอร์ชั่นของ MySQL ที่ติดตั้ง</p>
<pre>[root@centos54-a ~]# <strong>rpm -qa | grep -i mysql
</strong>MySQL-server-community-5.1.43-1.rhel5
MySQL-client-community-5.1.43-1.rhel5
MySQL-shared-compat-5.1.43-1.rhel5</pre>
<p>หมายเหตุ</p>
<ul>
<li>MySQL 5.1.43 ที่ทดสอบนี้ ใช้เวอร์ชั่นที่ดาวน์โหลดจาก <a href="http://dev.mysql.com">http://dev.mysql.com</a></li>
<li>แนะนำให้ใช้ MySQL เวอร์ชั่นเดียวกันบนเครื่อง Master และ Slave</li>
</ul>
<h4>เครื่อง Master &#8211; สร้าง user สำหรับ Replication</h4>
<p>เริ่มต้น ต้องสร้าง user ของ MySQL บนเครื่อง Master เพื่ออนุญาตสิทธิในการทำ &#8216;REPLICATION&#8217; จากเครื่อง Slave</p>
<p>ตัวอย่างการสร้าง user ชื่อ &#8216;repl&#8217; และรหัส &#8216;repl1234&#8242;เพื่อให้สิทธิการทำ REPLICATION จากเครื่องที่มี ip 192.168.1.2</p>
<pre>[root@centos54-a ~]# <strong>mysql -u root -p</strong></pre>
<pre>mysql&gt; <strong>GRANT REPLICATION SLAVE ON *.* TO '<span style="color: #0000ff;">repl</span>'@'<span style="color: #0000ff;">192.168.1.2</span>' IDENTIFIED BY '<span style="color: #0000ff;">repl1234</span>';</strong></pre>
<h4>เครื่อง Master &#8211; คอนฟิก Replication Master</h4>
<p>บนเครื่อง Master ปิดเซอร์วิส MySQL แล้วแก้ไขไฟล์ /etc/my.cnf เพื่อเปิดคุณสมบัติ binary log (log-bin) และเซ็ต server-id</p>
<pre>[root@centos54-a ~]# <strong>service mysql stop
</strong>Shutting down MySQL..                                      [  OK  ]</pre>
<p>ตัวอย่างไฟล์คอนฟิก /etc/my.cnf เพื่อคอนฟิกเป็น Replication Master</p>
<pre>[root@centos54-a ~]# <strong>cat /etc/my.cnf
</strong>[mysqld]
log-bin=mysql-bin
server-id=1</pre>
<p>ใช้คำสั่ง service เพื่อรันเซอร์วิส MySQL</p>
<pre>[root@centos54-a ~]# <strong>service mysql start
</strong>Starting MySQL.                                            [  OK  ]</pre>
<h4>เครื่อง Master &#8211; ตรวจสอบสถานะของ Master Binary Log</h4>
<p>บนเครื่อง Master ใช้คำสั่ง SHOW MASTER STATUS ตรวจสอบสถานะของ Master Binary Log</p>
<p>เราจะใช้ค่า &#8216;File&#8217; และ &#8216;Position&#8217; เพื่อระบุบนเครื่อง Slave</p>
<pre>[root@centos54-a ~]# <strong>mysql -u root -p</strong></pre>
<pre>mysql&gt; <strong>SHOW MASTER STATUS;
</strong>+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| <strong><span style="color: #0000ff;">mysql-bin.000001</span></strong> |      <strong><span style="color: #0000ff;">224</span> </strong>|              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)</pre>
<h4>เครื่อง Slave &#8211; คอนฟิก Replication Slave</h4>
<p>บนเครื่อง Slave ปิดเซอร์วิส MySQL เพื่อแก้ไขคอนฟิกไฟล์ /etc/my.cnf</p>
<pre>[root@centos54-b ~]# <strong>service mysql stop
</strong>Shutting down MySQL..                                      [  OK  ]</pre>
<p>เบื้องต้นบนเครื่อง Slave คอนฟิกแค่ &#8217;server-id&#8217; ที่มีค่าแตกต่างจากเครื่อง Master</p>
<pre>[root@centos54-b ~]# <strong>cat /etc/my.cnf
</strong>[mysqld]
server-id=2</pre>
<p>รันเซอร์วิส MySQL บนเครื่อง Slave</p>
<pre>[root@centos54-b ~]# <strong>service mysql start
</strong>Starting MySQL.                                            [  OK  ]</pre>
<p>ใช้คำสั่ง CHANGE MASTER เพื่อระบุ ip ของ Master ชื่อ user, password ที่ใช้เพื่อการทำ Replication และต้องระบุค่า log_file (File) และ log_pos (Position) ที่ได้จากผลลัพธ์ในการรันคำสั่ง SHOW MASTER STATUS บนเครื่อง Master</p>
<pre>mysql&gt; <strong>CHANGE MASTER TO MASTER_HOST='<span style="color: #0000ff;">192.168.1.1</span>',
                        MASTER_USER='<span style="color: #0000ff;">repl</span>',
                        MASTER_PASSWORD='<span style="color: #0000ff;">repl1234</span>',
                        MASTER_LOG_FILE='<span style="color: #0000ff;">mysql-bin.000001</span>',
                        MASTER_LOG_POS=<span style="color: #0000ff;">224</span>;
</strong>Query OK, 0 rows affected (0.03 sec)</pre>
<p>รันคำสั่ง START SLAVE เพื่อเริ่มต้นการทำ Replicate ข้อมูลจาก เครื่อง Master</p>
<pre>mysql&gt; <strong>START SLAVE;
</strong>Query OK, 0 rows affected (0.00 sec)</pre>
<p>ตรวจสอบสถานะ Replication บนเครื่อง Slave</p>
<pre>mysql&gt; <strong>SHOW SLAVE STATUS \G
</strong>*************************** 1. row ***************************
               <span style="color: #0000ff;">Slave_IO_State: Waiting for master to send event
</span>                  Master_Host: <span style="color: #0000ff;">192.168.1.1
</span>                  Master_User: <span style="color: #0000ff;">repl</span>
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: <span style="color: #0000ff;">mysql-bin.000001
</span>          Read_Master_Log_Pos: <span style="color: #0000ff;">244</span>
               Relay_Log_File: centos54-b-relay-bin.000004
                Relay_Log_Pos: 251
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 244
              Relay_Log_Space: 411
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
1 row in set (0.00 sec)</pre>
<p>หากคอนฟิกถูกต้อง ค่า &#8216;Slave_IO_State&#8217; จะแสดงเป็น &#8216;Waiting for master to send event&#8217;</p>
<h4>ทดสอบการ Replication</h4>
<p>เพื่อง่ายต่อการแยกแยะระหว่าง Master และ Slave ในที่นี้จะคอนฟิก mysql prompt เป็น mysql-1&gt; และ mysql-2&gt; ตามลำดับ</p>
<p>การคอนฟิก prompt บนเครื่อง Master</p>
<pre>[root@centos54-a ~]# <strong>mysql -u root -p
</strong>Enter password:</pre>
<pre>mysql&gt; <strong>PROMPT mysql-1&gt;
</strong>PROMPT set to 'mysql-1&gt; '
<span style="color: #0000ff;">mysql-1&gt;</span></pre>
<p>การคอนฟิก prompt บนเครื่อง Slave</p>
<pre>[root@centos54-b ~]# <strong>mysql -u root -p
</strong>Enter password:</pre>
<pre>mysql&gt; <strong>PROMPT mysql-2&gt;
</strong>PROMPT set to 'mysql-2&gt; '
<span style="color: #0000ff;">mysql-2&gt;</span></pre>
<p>ทดสอบสร้าง database บนเครื่อง Master</p>
<pre>mysql-1&gt; <strong>CREATE DATABASE <span style="color: #0000ff;">test1</span>;
</strong>Query OK, 1 row affected (0.01 sec)</pre>
<pre>mysql-1&gt; <strong>SHOW DATABASES;
</strong>+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| <span style="color: #0000ff;">test1</span>              |
+--------------------+
3 rows in set (0.00 sec)</pre>
<p>ข้อมูลการสร้าง database จะถูกส่งต่อ (replicate) ไปยังเครื่อง Slave โดยอัตโนมัติ</p>
<pre>mysql-2&gt; <strong>SHOW DATABASES;
</strong>+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| <span style="color: #0000ff;">test1</span>              |
+--------------------+
3 rows in set (0.00 sec)</pre>
<p>สร้าง table และทดสอบการ INSERT ข้อมูล</p>
<pre>mysql-1&gt; <strong>CONNECT test1
</strong>mysql-1&gt; <strong>CREATE TABLE books (id INTEGER, name VARCHAR(255));
</strong>mysql-1&gt; <strong>INSERT INTO books VALUES (1, 'how to setup...');
</strong>mysql-1&gt; <strong>INSERT INTO books VALUES (2, 'how to read...');</strong></pre>
<pre>mysql-1&gt; <strong>SELECT * FROM books;
</strong>+------+-----------------+
| id   | name            |
+------+-----------------+
|    1 | how to setup... |
|    2 | how to read...  |
+------+-----------------+
2 rows in set (0.00 sec)</pre>
<p>การเปลี่ยนแปลงบนเครื่อง Master จะถูก replicate ไปยังเครื่อง Slave โดยอัตโนมัติ</p>
<pre>mysql-2&gt; <strong>CONNECT test1;
</strong>mysql-2&gt; <strong>SELECT * FROM books;
</strong>+------+-----------------+
| id   | name            |
+------+-----------------+
|    1 | how to setup... |
|    2 | how to read...  |
+------+-----------------+
2 rows in set (0.00 sec)</pre>
<h4>ข้อมูลอ้างอิง</h4>
<ul>
<li><a href="http://dev.mysql.com/doc/refman/5.1/en/replication.html" target="_blank">MySQL 5.1 Reference Manual :: Replication</a></li>
<li><a href="http://spalinux.com/2009/02/install_mysql_51_on_fedora_10">ติดตั้ง MySQL 5.1 บน Fedora 10</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://spalinux.com/2010/02/configure_mysql_replication/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>การแสดงผล Error ของ PHP</title>
		<link>http://spalinux.com/2010/02/configure_display_php_errors</link>
		<comments>http://spalinux.com/2010/02/configure_display_php_errors#comments</comments>
		<pubDate>Fri, 12 Feb 2010 08:21:45 +0000</pubDate>
		<dc:creator>editor</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[php error]]></category>

		<guid isPermaLink="false">http://spalinux.com/?p=1077</guid>
		<description><![CDATA[การตรวจสอบข้อผิดพลาด (error) เวลาพัฒนาโปรแกรม หรือเมื่อรันโปรแกรม ถือว่ามีความสำคัญอย่างหนึ่ง เพื่อที่จะทำให้ระบบทำงานได้อย่างถูกต้อง
สำหรับการพัฒนา Web Application ด้วย PHP การตรวจสอบหรือแสดงผลข้อผิดพลาด สามารถทำได้ สองวิธีหลักๆ คือ

แสดงข้อผิดพลาด (error) ผ่านหน้าเว็บ
เก็บข้อผิดพลาดไว้ในไฟล์ (log file) เพื่อการตรวจสอบ


วิธีแรก การแสดงผลข้อผิดพลาด ผ่านหน้าเว็บเมื่อรันโปรแกรมเลย ถือว่ามีความสะดวกสบายมาก คือเมื่อโปรแกรมเมอร์พัฒนาโปรแกรมไป รันผ่านหน้าเว็บ ก็สามารถเห็นข้อผิดพลาดที่เกิดขึ้นได้เลย ว่าเกิดปัญหาที่ไหน ไฟล์อะไร บรรทัดเท่าไร
แต่จะมีข้อเสียอย่างมาก หากปล่อยให้มีการแสดงผลข้อผิดพลาดนี้ แก่ผู้ใช้งานทั่วไป เพราะอาจแสดงรายละเอียดโปรแกรมมากเกินไป ซึ่งอาจทำให้เปิดเผยช่องโหว่ของโปรแกรมได้
คำแนะนำคือ ในขณะที่กำลังพัฒนาโปรแกรม (development) หรือบนเครื่องเซิร์ฟเวอร์สำหรับทดสอบโปรแกรม เราอาจเปิดการแสดงผลข้อผิดพลาดผ่านหน้าเว็บเลย เพื่อสะดวกต่อโปรแกรมเมอร์ ในการตรวจสอบ
แต่เมื่อไรก็ตาม ระบบเริ่มใช้งานจริง (production) แนะนำให้ปิดการแสดงผลข้อผิดพลาดผ่านหน้าเว็บ ให้เก็บข้อผิดพลาดไว้ในแบบที่ 2 คือเก็บไว้ในไฟล์ (log file) แล้วดูข้อผิดพลาดจากในไฟล์
ตัวอย่างข้อผิดพลาดในการเขียน PHP เช่น พิมพ์เครื่องหมาย : แทนที่เป็น ;
$ cat /var/www/html/test.php
&#60;?php
print [...]]]></description>
			<content:encoded><![CDATA[<p>การตรวจสอบข้อผิดพลาด (error) เวลาพัฒนาโปรแกรม หรือเมื่อรันโปรแกรม ถือว่ามีความสำคัญอย่างหนึ่ง เพื่อที่จะทำให้ระบบทำงานได้อย่างถูกต้อง</p>
<p>สำหรับการพัฒนา Web Application ด้วย PHP การตรวจสอบหรือแสดงผลข้อผิดพลาด สามารถทำได้ สองวิธีหลักๆ คือ</p>
<ol>
<li>แสดงข้อผิดพลาด (error) ผ่านหน้าเว็บ</li>
<li>เก็บข้อผิดพลาดไว้ในไฟล์ (log file) เพื่อการตรวจสอบ</li>
</ol>
<p><span id="more-1077"></span></p>
<p>วิธีแรก การแสดงผลข้อผิดพลาด ผ่านหน้าเว็บเมื่อรันโปรแกรมเลย ถือว่ามีความสะดวกสบายมาก คือเมื่อโปรแกรมเมอร์พัฒนาโปรแกรมไป รันผ่านหน้าเว็บ ก็สามารถเห็นข้อผิดพลาดที่เกิดขึ้นได้เลย ว่าเกิดปัญหาที่ไหน ไฟล์อะไร บรรทัดเท่าไร</p>
<p>แต่จะมีข้อเสียอย่างมาก หากปล่อยให้มีการแสดงผลข้อผิดพลาดนี้ แก่ผู้ใช้งานทั่วไป เพราะอาจแสดงรายละเอียดโปรแกรมมากเกินไป ซึ่งอาจทำให้เปิดเผยช่องโหว่ของโปรแกรมได้</p>
<p>คำแนะนำคือ ในขณะที่กำลังพัฒนาโปรแกรม (development) หรือบนเครื่องเซิร์ฟเวอร์สำหรับทดสอบโปรแกรม เราอาจเปิดการแสดงผลข้อผิดพลาดผ่านหน้าเว็บเลย เพื่อสะดวกต่อโปรแกรมเมอร์ ในการตรวจสอบ</p>
<p>แต่เมื่อไรก็ตาม ระบบเริ่มใช้งานจริง (production) แนะนำให้ปิดการแสดงผลข้อผิดพลาดผ่านหน้าเว็บ ให้เก็บข้อผิดพลาดไว้ในแบบที่ 2 คือเก็บไว้ในไฟล์ (log file) แล้วดูข้อผิดพลาดจากในไฟล์</p>
<p>ตัวอย่างข้อผิดพลาดในการเขียน PHP เช่น พิมพ์เครื่องหมาย : แทนที่เป็น ;</p>
<pre>$ <strong>cat /var/www/html/test.php
</strong>&lt;?php</pre>
<pre>print 'hello'<span style="color: #ff0000;"><strong>:</strong></span></pre>
<pre>?&gt;</pre>
<h4>แสดงข้อผิดพลาดผ่านหน้าเว็บ (display_errors)</h4>
<p>PHP เวอร์ชั่นหลังๆ จะปิดการแสดงข้อผิดพลาดผ่านหน้าเว็บ หากต้องการเปิดคุณสมบัตินี้ทำได้สองวิธีคือ</p>
<p>1. แก้ไฟล์ /etc/php.ini จะมีผลทั้งเซิร์ฟเวอร์</p>
<p>ออปชั่นที่ต้องแก้ไขคือ &#8220;display_errors&#8221;</p>
<ul>
<li>&#8220;On&#8221; หากต้องการเปิดการแสดงผลข้อผิดพลาดผ่านหน้าเว็บ เหมาะสำหรับการพัฒนาโปรแกรม (development)</li>
<li>&#8220;Off&#8221; หากไม่ต้องการแสดงผลข้อผิดพลาดผ่านหน้าเว็บ สำหรับระบบที่ใช้งานจริงแล้ว (production)</li>
</ul>
<p>ตัวอย่างการคอนฟิกในไฟล์ /etc/php.ini</p>
<pre>...
display_errors = On
...</pre>
<p>หลังจากแก้ไขไฟล์ ต้องรีโหลด Web Server เพื่อให้คอนฟิกใหม่มีผล</p>
<pre># <strong>service httpd reload
</strong>Reloading httpd:                                           [  OK  ]</pre>
<p>ตัวอย่างการแสดงผลข้อผิดพลาดผ่านหน้าเว็บ</p>
<p><a href="http://spalinux.com/wp-content/uploads/2010/02/02-display_errors_with_html_errors.png"><img title="display_errors = On" src="http://spalinux.com/wp-content/uploads/2010/02/02-display_errors_with_html_errors.png" alt="" width="595" height="272" /></a></p>
<p>2. หากไม่สามารถแก้ไขไฟล์ /etc/php.ini ได้ สามารถใช้ฟังก์ชั่น &#8220;ini_set&#8221; เพื่อเปิดคุณสมบัตินี้ได้</p>
<p>ตัวอย่างการใช้ฟังก์ชั่น &#8220;ini_set&#8221; เพื่อตั้งค่าคอนฟิก &#8220;display_errors&#8221;</p>
<pre>&lt;?php

ini_set('display_errors', TRUE);
...
?&gt;</pre>
<h4>เก็บข้อผิดพลาดไว้ในไฟล์ (error_log)</h4>
<p>เมื่อระบบใช้งานจริง (production) แล้ว แนะนำให้ปิดการแสดงผลข้อผิดพลาดผ่านหน้าเว็บ แต่ให้เก็บไว้ในไฟล์ ไว้ดูย้อนหลังได้</p>
<p>ตัวอย่างคอนฟิกให้เก็บข้อผิดพลาดของการรัน PHP ไว้ในไฟล์ /var/log/httpd/php_errors.log</p>
<pre>...
html_errors = Off
log_errors = On
error_log = /var/log/httpd/php_errors.log
...</pre>
<p>ต้องสร้างไฟล์สำหรับเก็บ และตั้งค่าเจ้าของไฟล์ (owner) เพื่อให้โปรเซสเว็บเซิร์ฟเวอร์ เช่น apache เขียนไฟล์ได้</p>
<pre># <strong>touch /var/log/httpd/php_errors.log
</strong># <strong>chown apache /var/log/httpd/php_errors.log</strong></pre>
<p>หลังจากแก้ไขไฟล์ ต้องรีโหลด Web Server เพื่อให้คอนฟิกใหม่มีผล</p>
<pre># <strong>service httpd reload
</strong>Reloading httpd:                                           [  OK  ]</pre>
<p>ตัวอย่างข้อผิดพลาดที่ถูกเก็บไว้ในไฟล์</p>
<pre># <strong>tail -f /var/log/httpd/php_errors.log
</strong>[12-Feb-2010 12:49:25] PHP Parse error:  syntax error, unexpected ':' in /var/www/html/test.php on line 3</pre>
<p>หรือถ้าต้องการเก็บไว้ใน syslog ก็แก้คอนฟิก &#8220;error_log&#8221; ให้เป็น syslog ได้</p>
<pre>...
html_errors = Off
log_errors = On
error_log = syslog
...</pre>
<p>ตัวอย่างการแสดงผลในไฟล์ /var/log/messages</p>
<pre># <strong>tail -f /var/log/messages
</strong>Feb 12 15:05:08 web httpd: PHP Parse error:  syntax error, unexpected ':' in /var/www/html/test.php on line 3</pre>
]]></content:encoded>
			<wfw:commentRss>http://spalinux.com/2010/02/configure_display_php_errors/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>การใช้งาน DRBD เบื้องต้น</title>
		<link>http://spalinux.com/2010/02/basic_using_drbd</link>
		<comments>http://spalinux.com/2010/02/basic_using_drbd#comments</comments>
		<pubDate>Sat, 06 Feb 2010 11:09:40 +0000</pubDate>
		<dc:creator>editor</dc:creator>
				<category><![CDATA[Backup]]></category>
		<category><![CDATA[Cluster]]></category>
		<category><![CDATA[Disk]]></category>
		<category><![CDATA[Filesystem]]></category>
		<category><![CDATA[Kernel]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[drbd]]></category>
		<category><![CDATA[linux ha]]></category>

		<guid isPermaLink="false">http://spalinux.com/?p=1072</guid>
		<description><![CDATA[จากบทความ ติดตั้งและคอนฟิก DRBD  เราได้คอนฟิกเป็นแบบ Single-primary mode คือ ณ เวลาใดเวลาหนึ่ง มีเครื่องเดียวเท่านั้นที่สามารถ อ่าน เขียน ข้อมูลได้
ดังนั้นขณะที่เครื่องที่ 1 (centos54-a) ทำหน้าที่เป็น primary ของดิสก์ drbd0 อยู่  เครื่องที่ 2 (centos54-b) จะไม่สามารถ mount ดิสก์ drbd0 นี้ขึ้นมาใช้งานได้
ในบทความนี้จะแสดงการทดสอบใช้คำสั่งเพื่อเปลี่ยนโหมด Primary, Secondary ระหว่างเครื่องทั้งสอง
ตรวจสอบสถานะบนเครื่อง centos54-a
[root@centos54-a ~]# service drbd status
drbd driver loaded OK; device status:
version: 8.3.2 (api:88/proto:86-90)
GIT-hash: dd7985327f146f33b86d4bff5ca8c94234ce840e build by mockbuild@v20z-x86-64.home.local, 2009-08-29 14:07:55
m:res  cs         ro                 ds                 p  mounted  fstype
0:r0   [...]]]></description>
			<content:encoded><![CDATA[<p>จากบทความ <a href="http://spalinux.com/2010/02/install_and_configure_drbd">ติดตั้งและคอนฟิก DRBD </a> เราได้คอนฟิกเป็นแบบ Single-primary mode คือ ณ เวลาใดเวลาหนึ่ง มีเครื่องเดียวเท่านั้นที่สามารถ อ่าน เขียน ข้อมูลได้</p>
<p>ดังนั้นขณะที่เครื่องที่ 1 (centos54-a) ทำหน้าที่เป็น primary ของดิสก์ drbd0 อยู่  เครื่องที่ 2 (centos54-b) จะไม่สามารถ mount ดิสก์ drbd0 นี้ขึ้นมาใช้งานได้</p>
<p>ในบทความนี้จะแสดงการทดสอบใช้คำสั่งเพื่อเปลี่ยนโหมด Primary, Secondary ระหว่างเครื่องทั้งสอง</p>
<p>ตรวจสอบสถานะบนเครื่อง centos54-a</p>
<pre>[root@centos54-a ~]# <strong>service drbd status
</strong>drbd driver loaded OK; device status:
version: 8.3.2 (api:88/proto:86-90)
GIT-hash: dd7985327f146f33b86d4bff5ca8c94234ce840e build by mockbuild@v20z-x86-64.home.local, 2009-08-29 14:07:55
m:res  cs         ro                 ds                 p  mounted  fstype
0:r0   Connected  Primary/Secondary  UpToDate/UpToDate  C  /export  ext3</pre>
<pre>[root@centos54-a ~]# df -h /export
Filesystem            Size  Used Avail Use% Mounted on
/dev/drbd0            950M   18M  885M   2% /export</pre>
<p>ทดสอบ mount ดิสก์บนเครื่อง centos54-b</p>
<pre>[root@centos54-b ~]# <strong>service drbd status
</strong>drbd driver loaded OK; device status:
version: 8.3.2 (api:88/proto:86-90)
GIT-hash: dd7985327f146f33b86d4bff5ca8c94234ce840e build by mockbuild@v20z-x86-64.home.local, 2009-08-29 14:07:55
m:res  cs         ro                 ds                 p  mounted  fstype
0:r0   Connected  Secondary/Primary  UpToDate/UpToDate  C</pre>
<pre>[root@centos54-b ~]# mount /dev/drbd0 /export
mount: block device /dev/drbd0 is write-protected, mounting read-only
mount: Wrong medium type</pre>
<p>ในกรณีที่ต้องการเปลี่ยนให้เครื่องที่ 2 (centos54-b) ทำหน้าที่เป็น primary  เช่นในกรณีที่ต้องการซ่อมบำรุงเครื่องที่ 1 สามารถทำได้ดังนี้</p>
<p>บนเครื่องที่ 1 ปิดเซอร์วิส DRBD</p>
<pre>[root@centos54-a ~]# <strong>service drbd stop
</strong>Stopping all DRBD resources:
.
[root@centos54-a ~]# <strong>service drbd status
</strong>drbd not loaded</pre>
<p>ตรวจสอบสถานะบนเครื่องที่ 2 หลังจากปิดเซอร์วิสบนเครื่องที่ 1</p>
<pre>[root@centos54-b ~]# <strong>service drbd status
</strong>drbd driver loaded OK; device status:
version: 8.3.2 (api:88/proto:86-90)
GIT-hash: dd7985327f146f33b86d4bff5ca8c94234ce840e build by mockbuild@v20z-x86-64.home.local, 2009-08-29 14:07:55
m:res  cs            ro                 ds                 p  mounted  fstype
0:r0   WFConnection  <strong><span style="color: #0000ff;">Secondary</span></strong>/Unknown  UpToDate/DUnknown  C</pre>
<p>แม้เครื่อง Primary ปิดไปแล้ว บนเครื่องที่ 2 ที่ยังอยู่ในโหมด Secondary ก็ยัง mount ดิสก์ ไม่ได้</p>
<pre>[root@centos54-b ~]# <strong>mount /dev/drbd0 /export
</strong>mount: block device /dev/drbd0 is write-protected, mounting read-only
mount: Wrong medium type</pre>
<p>ต้องเปลี่ยนสถานะบนเครื่องที่ 2 ให้เป็น primary ด้วยคำสั่ง drbdadm primary</p>
<pre>[root@centos54-b ~]# <strong>drbdadm primary all</strong></pre>
<p>ตรวจสอบสถานะบนเครื่องที่ 2</p>
<pre>[root@centos54-b ~]# <strong>service drbd status
</strong>drbd driver loaded OK; device status:
version: 8.3.2 (api:88/proto:86-90)
GIT-hash: dd7985327f146f33b86d4bff5ca8c94234ce840e build by mockbuild@v20z-x86-64.home.local, 2009-08-29 14:07:55
m:res  cs            ro               ds                 p  mounted  fstype
0:r0   WFConnection  <span style="color: #0000ff;"><strong>Primary</strong></span>/Unknown  UpToDate/DUnknown  C</pre>
<p>เมื่ออยู่ในโหมด primary แล้ว ก็สามารถ mount ดิสก์ขึ้นมาใช้งานได้</p>
<pre>[root@centos54-b ~]# <strong>mount /dev/drbd0 /export
</strong>[root@centos54-b ~]# <strong>df -h /export
</strong>Filesystem            Size  Used Avail Use% Mounted on
/dev/drbd0            950M   18M  885M   2% /export</pre>
<p>ทดลองสร้างไฟล์ในดิสก์ drbd0</p>
<pre>[root@centos54-b ~]# <strong>cd /export/
</strong>[root@centos54-b export]# <strong>ls
</strong>lost+found
[root@centos54-b export]# <strong>echo "hello world from node 2" &gt; test-file-on-node-2.txt
</strong>[root@centos54-b export]# <strong>ls -l
</strong>total 20
drwx------ 2 root root 16384 Feb  6 15:46 lost+found
-rw-r--r-- 1 root root    24 Feb  6 17:17 <span style="color: #0000ff;"><strong>test-file-on-node-2.txt</strong></span></pre>
<p>รันเซอร์วิส DRBD บนเครื่องที่ 1 ขึ้นมาอีกครั้ง ตอนนี้เครื่องที่ 1 จะทำหน้าที่เป็น Secondary และจะทำการ replicate ข้อมูลมาจากเครื่องที่ 2 (Primary) โดยอัตโนมัติ</p>
<pre>[root@centos54-a ~]# <strong>service drbd start
</strong>Starting DRBD resources: [ d(r0) s(r0) n(r0) ].</pre>
<pre>[root@centos54-a ~]# <strong>service drbd status
</strong>drbd driver loaded OK; device status:
version: 8.3.2 (api:88/proto:86-90)
GIT-hash: dd7985327f146f33b86d4bff5ca8c94234ce840e build by mockbuild@v20z-x86-64.home.local, 2009-08-29 14:07:55
m:res  cs         ro                 ds                 p  mounted  fstype
0:r0   Connected  <strong><span style="color: #0000ff;">Secondary</span></strong>/Primary  UpToDate/UpToDate  C</pre>
<p>บนเครื่องที่ 2 เปลี่ยนให้เป็นโหมด Secondary</p>
<pre>[root@centos54-b ~]# <strong>drbdadm secondary all
</strong><span style="color: #ff0000;">0: State change failed: (-12) Device is held open by someone</span>
Command 'drbdsetup 0 secondary' terminated with exit code 11</pre>
<p>หากมีการเรียกใช้ดิสก์ drbd อยู่ จะไม่สามารถเปลี่ยนโหมดจาก Primary ไปเป็น Secondary ได้ ต้อง umount ดิสก์ออกไปก่อนถึงจะเปลี่ยนโหมดได้</p>
<pre>[root@centos54-b ~]# <strong>umount /export
</strong>[root@centos54-b ~]# <strong>drbdadm secondary all</strong></pre>
<p>ตรวจสอบสถานะบนเครื่องที่ 2</p>
<pre>[root@centos54-b ~]# <strong>service drbd status
</strong>drbd driver loaded OK; device status:
version: 8.3.2 (api:88/proto:86-90)
GIT-hash: dd7985327f146f33b86d4bff5ca8c94234ce840e build by mockbuild@v20z-x86-64.home.local, 2009-08-29 14:07:55
m:res  cs         ro                   ds                 p  mounted  fstype
0:r0   Connected  <span style="color: #0000ff;"><strong>Secondary</strong></span>/Secondary  UpToDate/UpToDate  C</pre>
<p>เปลี่ยนโหมดบนเครื่องที่ 1 ให้เป็น Primary เพื่อเรียกใช้ดิสก์ได้</p>
<pre>[root@centos54-a ~]# <strong>drbdadm primary all
</strong>[root@centos54-a ~]# <strong>service drbd status
</strong>drbd driver loaded OK; device status:
version: 8.3.2 (api:88/proto:86-90)
GIT-hash: dd7985327f146f33b86d4bff5ca8c94234ce840e build by mockbuild@v20z-x86-64.home.local, 2009-08-29 14:07:55
m:res  cs         ro                 ds                 p  mounted  fstype
0:r0   Connected  <strong><span style="color: #0000ff;">Primary</span></strong>/Secondary  UpToDate/UpToDate  C</pre>
<p>mount ดิสก์ และตรวจสอบไฟล์ที่อยู่ใน drbd0 จะเห็นไฟล์ที่สร้างจากเครื่องที่ 2</p>
<pre>[root@centos54-a ~]# <strong>mount /dev/drbd0 /export
</strong>[root@centos54-a ~]# <strong>cd /export/
</strong>[root@centos54-a export]# ls -l
total 20
drwx------ 2 root root 16384 Feb  6 15:46 lost+found
-rw-r--r-- 1 root root    24 Feb  6 17:17 <strong><span style="color: #0000ff;">test-file-on-node-2.txt
</span></strong>[root@centos54-a export]# <strong>cat test-file-on-node-2.txt
</strong>hello world from node 2</pre>
<h4>ตรวจสอบไฟล์ /var/log/messages</h4>
<p>เมื่อมีปัญหาเกี่ยวกับการใช้ DBRD นอกจากการใช้คำสั่ง service เพื่อตรวจสอบสถานะแล้ว ไฟล์ /var/log/messages จะแสดงการเปลี่ยนแปลงทั้งหมดของ DRBD ที่เกิดขึ้น ซึ่งสามารถนำมาใช้ช่วยในการแก้ปัญหาได้</p>
<p>ตัวอย่างข้อความในไฟล์ /var/log/messages ที่เกิดขึ้น เมื่อมีการเปลี่ยนโหมด</p>
<pre>[root@centos54-a ~]# <strong>tail /var/log/messages
</strong>...
Feb  6 17:19:38 centos54-a kernel: block drbd0: peer( Primary -&gt; Secondary )
Feb  6 17:21:04 centos54-a kernel: block drbd0: role( Secondary -&gt; Primary )
...</pre>
<h4>ข้อมูลอ้างอิง</h4>
<ul>
<li><a href="http://spalinux.com/2010/02/install_and_configure_drbd">ติดตั้งและคอนฟิก DRBD</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://spalinux.com/2010/02/basic_using_drbd/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ติดตั้งและคอนฟิก DRBD</title>
		<link>http://spalinux.com/2010/02/install_and_configure_drbd</link>
		<comments>http://spalinux.com/2010/02/install_and_configure_drbd#comments</comments>
		<pubDate>Sat, 06 Feb 2010 09:40:46 +0000</pubDate>
		<dc:creator>editor</dc:creator>
				<category><![CDATA[Backup]]></category>
		<category><![CDATA[Cluster]]></category>
		<category><![CDATA[Disk]]></category>
		<category><![CDATA[Filesystem]]></category>
		<category><![CDATA[Kernel]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[drbd]]></category>
		<category><![CDATA[linux ha]]></category>

		<guid isPermaLink="false">http://spalinux.com/?p=1068</guid>
		<description><![CDATA[DRBD (Distributed Replicated Block Device) เป็นโปรแกรมเพื่อใช้ในการ replicate ข้อมูลดิสก์ที่อยู่คนละเครื่องกัน ผ่านทางเน็ตเวิร์ก โดยจะทำในระดับ block ของดิสก์
เมื่อมีการเปลี่ยนแปลงข้อมูลที่อยูในดิสก์เครื่องหนึ่ง (primary) การเปลี่ยนแปลงนั้นจะถูก replicate ไปยังอีกเครื่อง (secondary) โดยอัตโนมัติ
DRBD ประกอบด้วยสองส่วนคือ
1. Kernel module &#8211; DRBD ทำหน้าที่ใน kernel โดยจะสร้าง virtual block device คั่นกลางระหว่าง physical disk กับ filesystem ที่สร้างอยู่ ไม่ว่าจะเป็น ext3, ext4, xfs
2. User space administration tools &#8211; เป็นโปรแกรมที่ช่วยในการจัดการ DRBD ได้ง่ายขึ้น หลักๆ จะเป็น drbdadm
ในบทความนี้จะแสดงการติดตั้งโปรแกรม DRBD และคอนฟิกเป็นแบบ Single-primary mode คือ [...]]]></description>
			<content:encoded><![CDATA[<p>DRBD (Distributed Replicated Block Device) เป็นโปรแกรมเพื่อใช้ในการ replicate ข้อมูลดิสก์ที่อยู่คนละเครื่องกัน ผ่านทางเน็ตเวิร์ก โดยจะทำในระดับ block ของดิสก์</p>
<p>เมื่อมีการเปลี่ยนแปลงข้อมูลที่อยูในดิสก์เครื่องหนึ่ง (primary) การเปลี่ยนแปลงนั้นจะถูก replicate ไปยังอีกเครื่อง (secondary) โดยอัตโนมัติ</p>
<p>DRBD ประกอบด้วยสองส่วนคือ</p>
<p>1. Kernel module &#8211; DRBD ทำหน้าที่ใน kernel โดยจะสร้าง virtual block device คั่นกลางระหว่าง physical disk กับ filesystem ที่สร้างอยู่ ไม่ว่าจะเป็น ext3, ext4, xfs<br />
2. User space administration tools &#8211; เป็นโปรแกรมที่ช่วยในการจัดการ DRBD ได้ง่ายขึ้น หลักๆ จะเป็น drbdadm</p>
<p>ในบทความนี้จะแสดงการติดตั้งโปรแกรม DRBD และคอนฟิกเป็นแบบ Single-primary mode คือ ณ เวลาใดเวลาหนึ่ง มีเครื่องเดียวเท่านั้นที่สามารถ อ่าน เขียน ข้อมูลได้</p>
<p><span style="color: #ff0000;"><strong>คำเตือน ติดตั้งและคอนฟิก DRBD บนเครื่องทดสอบให้เข้าใจก่อน เพราะบางคำสั่งอาจกระทบข้อมูลดิสก์หรือ partition ที่มีอยู่ในเครื่องได้ ทำให้ข้อมูลเสียหายได้</strong></span></p>
<p><span id="more-1068"></span></p>
<h4>ระบบสำหรับการทดสอบ</h4>
<p>ในที่นี้จะติดตั้ง CentOS 5.4 พร้อมคอนฟิกให้สองเครื่องติดต่อ ping กันได้ และปิดคุณสมบัติ firewall ทั้งหมด</p>
<p><strong>เครื่องที่ 1</strong></p>
<ul>
<li>Hostname:   centos54-a.spalinux.com</li>
<li>IP Address: 10.3.3.51</li>
</ul>
<p><strong>เครื่องที่ 2</strong></p>
<ul>
<li>Hostname:   centos54-b.spalinux.com</li>
<li>IP Address: 10.3.3.52</li>
</ul>
<p>แก้ไขไฟล์ /etc/hosts เพื่อให้ทั้งสองเครื่องอ้างอิงจากชื่อเครื่องได้</p>
<p>ตัวอย่างคอนฟิกของเครื่องที่ 1</p>
<pre>[root@centos54-a ~]# <strong>hostname</strong>
centos54-a.spalinux.com</pre>
<pre>[root@centos54-a ~]# <strong>cat /etc/hosts
</strong># Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1       localhost.localdomain localhost
::1             localhost6.localdomain6 localhost6</pre>
<pre>10.3.3.51       centos54-a centos54-a.spalinux.com
10.3.3.52       centos54-b centos54-b.spalinux.com</pre>
<p>ตัวอย่างคอนฟิกของเครื่องที่ 2</p>
<pre>[root@centos54-b ~]# <strong>hostname</strong>
centos54-b.spalinux.com</pre>
<pre>[root@centos54-b ~]# <strong>cat /etc/hosts
</strong># Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1       localhost.localdomain localhost
::1             localhost6.localdomain6 localhost6</pre>
<pre>10.3.3.51       centos54-a centos54-a.spalinux.com
10.3.3.52       centos54-b centos54-b.spalinux.com</pre>
<p>ทั้งสองเครื่อง ต้องสร้าง partition สำหรับใช้เป็นดิสก์ DRBD โดยไม่ต้องสร้าง filesystem ใดๆ ทั้งสิ้นบน partition นี้ สมมติว่าเป็น /dev/sda5 บนทั้งสองเครื่อง</p>
<p>หมายเหตุ</p>
<ul>
<li>แนะนำให้สร้าง partition ทั้งสองเครื่องให้เหมือนกัน ขนาดเท่ากัน จะได้ง่ายต่อการคอนฟิก</li>
<li>สำหรับการทดสอบเริ่มต้น แนะนำให้สร้างขนาด partition เล็กๆ ก่อน จะได้ใช้เวลาในการ sync ข้อมูลไม่นานมากนัก ในบทความนี้สร้างประมาณ 1 GBytes</li>
</ul>
<h4>ติดตั้งโปรแกรม DRBD</h4>
<p>ไฟล์ติดตั้ง DRBD ในรูปแบบ rpm ของ CentOS 5.4 นั้น ไม่อยู่ในแผ่นดีวีดีติดตั้ง แต่จะอยู่ในส่วนของ extras สำหรับในเมืองไทยสามารถดาวน์โหลดได้จาก <a href="http://www.mirror.in.th/osarchive/centos/5.4/extras/">http://www.mirror.in.th/osarchive/centos/5.4/extras/</a></p>
<p>ดาวน์โหล์ด และติดตั้งไฟล์ rpm สองไฟล์ บนเครื่องทั้งสอง</p>
<ul>
<li>drbd83-8.3.2-6.el5_3.x86_64.rpm  &#8211; &#8220;User space administration tools&#8221;</li>
<li>kmod-drbd83-8.3.2-6.el5_3.x86_64.rpm  &#8211; &#8220;Kernel Module&#8221;</li>
</ul>
<p>ใช้คำสั่ง rpm เพื่อติดตั้ง</p>
<pre>[root@centos54-a ~]# <strong>rpm -ivh drbd83-8.3.2-6.el5_3.x86_64.rpm
</strong>Preparing...                ########################################### [100%]
   1:drbd83                 ########################################### [100%]
[root@centos54-a ~]# <strong>rpm -ivh kmod-drbd83-8.3.2-6.el5_3.x86_64.rpm
</strong>Preparing...                ########################################### [100%]
   1:kmod-drbd83            ########################################### [100%]</pre>
<h4>คอนฟิก DRBD บนเครื่องที่ 1 (primary)</h4>
<p>ไฟล์คอนฟิกหลักของ DRBD คือไฟล์ /etc/drbd.conf ต้องมีการแก้ไขไฟล์นี้ก่อนถึงจะเริ่มใช้งานได้ โดยมีไฟล์ตัวอย่างคอนฟิกอยู่ใน /usr/share/doc/drbd83/drbd.conf</p>
<p>ไฟล์คอนฟิก /etc/drbd.conf จากการติดตั้ง</p>
<pre>[root@centos54-a ~]# <strong>cat /etc/drbd.conf
</strong>#
# please have a a look at the example configuration file in
# /usr/share/doc/drbd83/drbd.conf
#</pre>
<p>สร้างไฟล์คอนฟิก /etc/drbd.conf บนเครื่องที่ 1 &#8220;centos54-a.spalinux.com&#8221; ดังนี้</p>
<pre>[root@centos54-a ~]# <strong>cat /etc/drbd.conf
</strong>global {
    usage-count no;
}</pre>
<pre>common {
    syncer { rate 10M; }
}</pre>
<pre>resource <strong><span style="color: #0000ff;">r0</span> </strong>{
    protocol C;</pre>
<pre>    net {
        cram-hmac-alg "sha1";
        shared-secret "<span style="color: #0000ff;"><strong>test1234</strong></span>";
    }</pre>
<pre>    on <strong><span style="color: #0000ff;">centos54-a.spalinux.com</span></strong> {
        device /dev/drbd0;
        <strong><span style="color: #0000ff;">disk /dev/sda5</span></strong>;
        <strong><span style="color: #0000ff;">address 10.3.3.51:8888</span></strong>;
        meta-disk internal;
    }</pre>
<pre>    on <strong><span style="color: #0000ff;">centos54-b.spalinux.com</span></strong> {
        device /dev/drbd0;
        <strong><span style="color: #0000ff;">disk /dev/sda5</span></strong>;
        <strong><span style="color: #0000ff;">address 10.3.3.52:8888</span></strong>;
        meta-disk internal;
    }
}</pre>
<p>คำอธิบายเบื้องต้น</p>
<ul>
<li>shared-secret เป็นการกำหนดรหัสของเครื่องที่สามารถ replicate ข้อมูลกันได้ </li>
<li>r0 เป็นชื่อ resource ของ DRBD สามารถตั้งเป็นชื่อใดๆ ก็ได้ เพื่อสื่อความหมาย</li>
<li>on ตามด้วยชื่อ hostname ที่ต้องการ replicate ข้อมูลกัน ส่วนในวงเล็บ { เป็นการกำหนดคอนฟิกของแต่ละเครื่อง</li>
<li>disk คือชื่อ partition ที่สร้างไว้สำหรับการทำ DRBD ในที่นี้คือ /dev/sda5</li>
</ul>
<p>ใช้คำสั่ง drbadm create-md เพื่อสร้าง meta data บน partition ที่จะทำเป็น DRBD</p>
<pre>[root@centos54-a ~]# <strong>drbdadm create-md all
</strong>Writing meta data...
initializing activity log
NOT initialized bitmap
New drbd meta data block successfully created.</pre>
<p>หาก partition ที่คอนฟิกเป็น DRBD มี filesystem อยู่ก่อนแล้ว จะไม่สามารถสร้าง DRBD ได้</p>
<pre>[root@centos54-a ~]# <strong>drbdadm create-md all
</strong>md_offset 1011671040
al_offset 1011638272
bm_offset 1011605504</pre>
<pre><span style="color: #ff0000;">Found ext3 filesystem</span> which uses 987964 kB
current configuration leaves usable 987896 kB</pre>
<pre>Device size would be truncated, which
would corrupt data and result in
'access beyond end of device' errors.
You need to either
   * use external meta data (recommended)
   * shrink that filesystem first
   * zero out the device (destroy the filesystem)
<span style="color: #ff0000;">Operation refused.</span></pre>
<pre>Command 'drbdmeta 0 v08 /dev/sda5 internal create-md' terminated with exit code 40
<span style="color: #ff0000;">drbdadm create-md r0: exited with code 40</span></pre>
<p>วิธีการแก้ไขคือต้องลบข้อมูลของ filesystem บน partition /dev/sda5 นี้ออก วิธีการง่ายสุดคือใช้คำสั่ง dd</p>
<p><span style="color: #ff0000;"><strong>คำเตือน คำสั่ง dd จะลบข้อมูลทั้งหมดบน partition ที่ระบุ</strong></span></p>
<pre>[root@centos54-a ~]# <strong>dd if=/dev/zero of=/dev/sda5
</strong>dd: writing to `/dev/sda5': No space left on device
1975933+0 records in
1975932+0 records out
1011677184 bytes (1.0 GB) copied, 87.2749 seconds, 11.6 MB/s</pre>
<p>แล้วถึงสามารถสร้าง meta data ของ DRBD ได้</p>
<pre>[root@centos54-a ~]# <strong>drbdadm create-md all
</strong>Writing meta data...
initializing activity log
NOT initialized bitmap
New drbd meta data block successfully created.</pre>
<p>ใช้คำสั่ง service เพื่อรันเซอร์วิส DRBD</p>
<pre>[root@centos54-a ~]# <strong>service drbd start
</strong>Starting DRBD resources: [ d(r0) s(r0) n(r0) ]..........
***************************************************************
 DRBD's startup script waits for the peer node(s) to appear.
 - In case this node was already a degraded cluster before the
   reboot the timeout is 0 seconds. [degr-wfc-timeout]
 - If the peer was available before the reboot the timeout will
   expire after 0 seconds. [wfc-timeout]
   (These values are for resource 'r0'; 0 sec -&gt; wait forever)
 To abort waiting enter 'yes' [  20]:<span style="color: #3366ff;"><strong><span style="color: #0000ff;">yes</span></strong></span></pre>
<p>ในครั้งแรกที่รันเซอร์วิส บนเครื่อง primary โปรแกรมจะรอให้เครื่อง peer (secondary) เข้ามาเชื่อมต่อ หากไม่ต้องการให้รอ ให้พิมพ์คำว่า &#8220;yes&#8221; แล้ว [Enter]</p>
<p>ใช้คำสั่ง service status เพื่อตรวจสอบสถานะของ DRBD</p>
<pre>[root@centos54-a ~]# <strong>service drbd status
</strong>drbd driver loaded OK; device status:
version: 8.3.2 (api:88/proto:86-90)
GIT-hash: dd7985327f146f33b86d4bff5ca8c94234ce840e build by mockbuild@v20z-x86-64.home.local, 2009-08-29 14:07:55
m:res  cs            ro                 ds                     p  mounted  fstype
0:r0   WFConnection  <span style="color: #0000ff;"><strong>Secondary</strong></span>/Unknown  <span style="color: #0000ff;"><strong>Inconsistent</strong></span>/DUnknown  C</pre>
<p>หรืออ่านจากไฟล์ /proc/drbd โดยตรง</p>
<pre>[root@centos54-a ~]# <strong>cat /proc/drbd</strong>
version: 8.3.2 (api:88/proto:86-90)
GIT-hash: dd7985327f146f33b86d4bff5ca8c94234ce840e build by mockbuild@v20z-x86-64.home.local, 2009-08-29 14:07:55
 0: cs:WFConnection ro:Secondary/Unknown ds:Inconsistent/DUnknown C r----
    ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b oos:987896</pre>
<p>สร้างไดเรคทอรี /export สำหรับทดสอบ mount เพื่อใช้ดิสก์ drbd ที่สร้างขึ้น</p>
<pre>[root@centos54-a ~]# <strong>mount /dev/drbd0 /export
</strong>mount: block device /dev/drbd0 is write-protected, mounting read-only
mount: Wrong medium type</pre>
<p>ดิสก์นี้ยังไม่สามารถใช้ได้ ต้องใช้คำสั่ง drbdadm primary คอนฟิกให้ดิสก์ drbd บนเครื่องนี้ทำหน้าที่เป็น primary เพื่อให้สามารถ อ่าน เขียน ข้อมูลจากดิสก์ได้</p>
<pre>[root@centos54-a ~]# <strong>drbdadm primary all
</strong><span style="color: #ff0000;">0: State change failed: (-2) Refusing to be Primary without at least one UpToDate disk
</span>Command 'drbdsetup 0 primary' terminated with exit code 17</pre>
<p>หากเป็นการเรียกใช้ครั้งแรก ต้องระบุออปชั่นดังนี้</p>
<pre>[root@centos54-a ~]# <strong>drbdadm -- --overwrite-data-of-peer primary all
</strong>[root@centos54-a ~]#</pre>
<p>ตรวจสอบสถานะ drbd อีกครั้ง สังเกตว่า ฟิลด์ ro จะเปลี่ยนจาก Seconday เป็น Primary และฟิลด์ ds จะเปลี่ยนจาก Inconsistent เป็น UpToDate</p>
<pre>[root@centos54-a ~]# <strong>service drbd status
</strong>drbd driver loaded OK; device status:
version: 8.3.2 (api:88/proto:86-90)
GIT-hash: dd7985327f146f33b86d4bff5ca8c94234ce840e build by mockbuild@v20z-x86-64.home.local, 2009-08-29 14:07:55
m:res  cs            ro               ds                 p  mounted  fstype
0:r0   WFConnection  <span style="color: #0000ff;"><strong>Primary</strong></span>/Unknown  <strong><span style="color: #0000ff;">UpToDate</span></strong>/DUnknown  C</pre>
<p>ทดสอบการ mount ดิสก์อีกครั้ง</p>
<pre>[root@centos54-a ~]# <strong>mount /dev/drbd0 /export
</strong>mount: you must specify the filesystem type</pre>
<p>ก็ยังไม่สามารถ mount ได้ เพราะยังไม่มี filesystem บน /dev/drbd0</p>
<p>รันคำสั่ง mkfs.ext3 เพื่อสร้าง filesystem แบบ ext3</p>
<pre>[root@centos54-a ~]# <strong>mkfs.ext3 /dev/drbd0
</strong>mke2fs 1.39 (29-May-2006)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
123648 inodes, 246974 blocks
12348 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=255852544
8 block groups
32768 blocks per group, 32768 fragments per group
15456 inodes per group
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376</pre>
<pre>Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done</pre>
<pre>This filesystem will be automatically checked every 36 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.</pre>
<p>ทดสอบการ mount อีกครั้ง จะสามารถใช้งานได้แล้ว</p>
<pre>[root@centos54-a ~]# <strong>mount /dev/drbd0 /export</strong></pre>
<p>ตรวจสอบสถานะ DRBD</p>
<pre>[root@centos54-a ~]# <strong>service drbd status
</strong>drbd driver loaded OK; device status:
version: 8.3.2 (api:88/proto:86-90)
GIT-hash: dd7985327f146f33b86d4bff5ca8c94234ce840e build by mockbuild@v20z-x86-64.home.local, 2009-08-29 14:07:55
m:res  cs            ro               ds                 p  mounted  fstype
0:r0   WFConnection  Primary/Unknown  UpToDate/DUnknown  C  <span style="color: #0000ff;"><strong>/export  ext3</strong></span></pre>
<h4>คอนฟิก DRBD บนเครื่องที่ 2 (secondary)</h4>
<p>สร้างไฟล์คอนฟิก /etc/drbd.conf บนเครื่องที่ 2 เหมือนกับไฟล์ในเครื่องที่ 1</p>
<pre>[root@centos54-b ~]# <strong>cat /etc/drbd.conf
</strong>global {
    usage-count no;
}</pre>
<pre>common {
    syncer { rate 10M; }
}</pre>
<pre>resource r0 {
    protocol C;</pre>
<pre>    net {
        cram-hmac-alg "sha1";
        shared-secret "test1234";
    }</pre>
<pre>    on centos54-a.spalinux.com {
        device /dev/drbd0;
        disk /dev/sda5;
        address 10.3.3.51:8888;
        meta-disk internal;
    }</pre>
<pre>    on centos54-b.spalinux.com {
        device /dev/drbd0;
        disk /dev/sda5;
        address 10.3.3.52:8888;
        meta-disk internal;
    }
}</pre>
<p>ใช้คำสั่ง drbadm create-md เพื่อสร้าง meta data บน partition ที่จะทำเป็น DRBD</p>
<pre>[root@centos54-b ~]# <strong>drbdadm create-md all
</strong>Writing meta data...
initializing activity log
NOT initialized bitmap
New drbd meta data block successfully created.</pre>
<p>เช่นเดียวกัน หากมี filesystem อยู่บน partition ก่อนแล้ว ต้องใช้คำสั่ง dd เพื่อลบข้อมูลออก</p>
<p>ใช้คำสั่ง service เพื่อรันเซอร์วิส DRBD</p>
<pre>[root@centos54-b ~]# <strong>service drbd start
</strong>Starting DRBD resources: [ d(r0) s(r0) n(r0) ].</pre>
<p>เมื่อเริ่มต้นรันเซอร์วิส DRBD บนเครื่องที่ 2 จะเป็นการเริ่ม replicate ข้อมูลจากเครื่องที่ 1</p>
<p>ตรวจสอบสถานะ DRBD บนเครื่องที่ 2</p>
<pre>[root@centos54-b ~]# <strong>service drbd status
</strong>drbd driver loaded OK; device status:
version: 8.3.2 (api:88/proto:86-90)
GIT-hash: dd7985327f146f33b86d4bff5ca8c94234ce840e build by mockbuild@v20z-x86-64.home.local, 2009-08-29 14:07:55
m:res  cs          ro                 ds                     p  mounted  fstype
...    <strong><span style="color: #0000ff;">sync'ed:    42.2%</span> </strong>             (576248/987896)K
0:r0   <strong><span style="color: #0000ff;">SyncTarget</span></strong>  <strong><span style="color: #0000ff;">Secondary</span></strong>/Primary  <span style="color: #0000ff;"><strong>Inconsistent</strong></span>/UpToDate  C</pre>
<p>ตรวจสอบสถานะ DRBD บนเครื่องที่ 1</p>
<pre>[root@centos54-a ~]# <strong>service drbd status
</strong>drbd driver loaded OK; device status:
version: 8.3.2 (api:88/proto:86-90)
GIT-hash: dd7985327f146f33b86d4bff5ca8c94234ce840e build by mockbuild@v20z-x86-64.home.local, 2009-08-29 14:07:55
m:res  cs          ro                 ds                     p  mounted  fstype
...    <strong><span style="color: #0000ff;">sync'ed:    43.0%</span></strong>              (567032/987896)K
0:r0   <strong><span style="color: #0000ff;">SyncSource</span></strong>  Primary/<strong><span style="color: #0000ff;">Secondary</span>  </strong>UpToDate/<strong><span style="color: #0000ff;">Inconsistent</span></strong>  C  /export  ext3</pre>
<p>เมื่อ replicate ข้อมูลเรียบร้อย (synced) ข้อมูลแล้ว สถานะจะเป็นดังนี้</p>
<p>ตรวจสอบสถานะ DRBD บนเครื่องที่ 2 เมื่อ synced ข้อมูลเรียบร้อย</p>
<pre>[root@centos54-b ~]# <strong>service drbd status
</strong>drbd driver loaded OK; device status:
version: 8.3.2 (api:88/proto:86-90)
GIT-hash: dd7985327f146f33b86d4bff5ca8c94234ce840e build by mockbuild@v20z-x86-64.home.local, 2009-08-29 14:07:55
m:res  cs         ro                 ds                 p  mounted  fstype
0:r0   <strong><span style="color: #0000ff;">Connected</span>  <span style="color: #0000ff;">Secondary</span></strong>/Primary  <strong><span style="color: #0000ff;">UpToDate</span></strong>/UpToDate  C</pre>
<p>ตรวจสอบสถานะ DRBD บนเครื่องที่ 1 เมื่อ synced ข้อมูลเรียบร้อย</p>
<pre>[root@centos54-a ~]# <strong>service drbd status
</strong>drbd driver loaded OK; device status:
version: 8.3.2 (api:88/proto:86-90)
GIT-hash: dd7985327f146f33b86d4bff5ca8c94234ce840e build by mockbuild@v20z-x86-64.home.local, 2009-08-29 14:07:55
m:res  cs         ro                 ds                 p  mounted  fstype
0:r0   <strong><span style="color: #0000ff;">Connected</span></strong>  Primary/<strong><span style="color: #0000ff;">Secondary</span></strong>  UpToDate/<strong><span style="color: #0000ff;">UpToDate</span></strong>  C  /export  ext3</pre>
<p>หลังจาก synced ข้อมูลระหว่างเครื่องเรียบร้อย เมื่อมีการเปลี่ยนแปลงข้อมูลในดิสก์บนเครื่องที่ 1 (primary) การเปลี่ยนแปลงนั้นจะถูก replicate ไปยังเครื่องที่ 2 (secondary) โดยอัตโนมัติ</p>
<p>ตัวอย่างการใช้คำสั่ง tcpdump  ตรวจสอบ packet ที่ส่งระหว่างเครื่องเพื่อการ replicate ข้อมูลของ DRBD</p>
<pre>[root@centos54-b ~]# <strong>tcpdump -i eth0 -l -nn | grep 8888
</strong>tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
15:51:39.815802 IP 10.3.3.52.8888 &gt; 10.3.3.51.42180: P 2834377596:2834377604(8) ack 2893184807 win 46 &lt;nop,nop,timestamp 1772852 1818781&gt;
15:51:39.816356 IP 10.3.3.51.42180 &gt; 10.3.3.52.8888: P 1:9(8) ack 8 win 3216 &lt;nop,nop,timestamp 1828655 1772852&gt;
15:51:39.816394 IP 10.3.3.52.8888 &gt; 10.3.3.51.42180: . ack 9 win 46 &lt;nop,nop,timestamp 1772852 1828655&gt;
15:51:44.888876 IP 10.3.3.1.4117 &gt; 10.3.3.51.22: P 1560:1612(52) ack 1629 win 64271
15:51:49.815252 IP 10.3.3.51.42180 &gt; 10.3.3.52.8888: P 9:17(8) ack 8 win 3216 &lt;nop,nop,timestamp 1838655 1772852&gt;
15:51:49.815330 IP 10.3.3.52.8888 &gt; 10.3.3.51.42180: . ack 17 win 46 &lt;nop,nop,timestamp 1782853 1838655&gt;
15:51:49.815666 IP 10.3.3.52.8888 &gt; 10.3.3.51.42180: P 8:16(8) ack 17 win 46 &lt;nop,nop,timestamp 1782853 1838655&gt;
15:51:49.847300 IP 10.3.3.51.42180 &gt; 10.3.3.52.8888: . ack 16 win 3216 &lt;nop,nop,timestamp 1838696 1782853&gt;
15:51:50.937877 IP 10.3.3.51.8888 &gt; 10.3.3.52.40284: . 3903780263:3903781711(1448) ack 2834246899 win 501 &lt;nop,nop,timestamp 1839875 1683335&gt;
...
<strong><span style="color: #0000ff;">[Ctrl-C]</span></strong></pre>
<h4>ข้อมูลอ้างอิง</h4>
<ul>
<li><a href="http://www.drbd.org/" target="_blank">DRBD</a></li>
<li><a href="http://www.mirror.in.th/osarchive/centos/5.4/extras/" target="_blank">CentOS 5.4 extras</a></li>
<li><a href="http://spalinux.com/2010/02/basic_using_drbd">การใช้งาน DRBD เบื้องต้น</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://spalinux.com/2010/02/install_and_configure_drbd/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ทดสอบ FOREIGN KEY Constraints ใน MySQL</title>
		<link>http://spalinux.com/2010/01/testing_mysql_foreign_key_constraints</link>
		<comments>http://spalinux.com/2010/01/testing_mysql_foreign_key_constraints#comments</comments>
		<pubDate>Sat, 23 Jan 2010 10:13:04 +0000</pubDate>
		<dc:creator>editor</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[mysql constraints]]></category>
		<category><![CDATA[mysql foreign key]]></category>

		<guid isPermaLink="false">http://spalinux.com/?p=1061</guid>
		<description><![CDATA[บทความนี้ต่อจาก การสร้าง FOREIGN KEY Constraints ใน MySQL เพื่อทดสอบการ เพิ่ม แก้ไข ลบ ข้อมูล โดยในเวลาเริ่มแต่ละหัวข้อจะใช้ข้อมูลนี้เป็นหลัก
mysql&#62; SELECT * FROM groups;
+----------+------------+
&#124; group_id &#124; group_name &#124;
+----------+------------+
&#124;      101 &#124; Accounting &#124;
&#124;      102 &#124; Engineer   &#124;
&#124;      103 &#124; IT         &#124;
&#124;      104 &#124; Manager    &#124;
+----------+------------+
4 rows in set (0.00 sec)
mysql&#62; SELECT * FROM users;
+---------+----------+-----------+
&#124; user_id &#124; group_id &#124; user_name &#124;
+---------+----------+-----------+
&#124;     501 &#124;      101 &#124; [...]]]></description>
			<content:encoded><![CDATA[<p>บทความนี้ต่อจาก <a href="http://spalinux.com/2010/01/creating_mysql_foreign_key_constraints">การสร้าง FOREIGN KEY Constraints ใน MySQL</a> เพื่อทดสอบการ เพิ่ม แก้ไข ลบ ข้อมูล โดยในเวลาเริ่มแต่ละหัวข้อจะใช้ข้อมูลนี้เป็นหลัก</p>
<pre><span id="more-1061"></span>mysql&gt; <strong>SELECT * FROM groups;
</strong>+----------+------------+
| group_id | group_name |
+----------+------------+
|      101 | Accounting |
|      102 | Engineer   |
|      103 | IT         |
|      104 | Manager    |
+----------+------------+
4 rows in set (0.00 sec)</pre>
<pre>mysql&gt; <strong>SELECT * FROM users;
</strong>+---------+----------+-----------+
| user_id | group_id | user_name |
+---------+----------+-----------+
|     501 |      101 | Ms.A      |
|     502 |      102 | Ms.B      |
|     503 |      102 | Mr.C      |
|     504 |      103 | Mr.D      |
|     505 |      104 | Mr.E      |
+---------+----------+-----------+
5 rows in set (0.00 sec)</pre>
<h4>การ DELETE ข้อมูล</h4>
<p>หลังจากใส่ FOREIGN KEY ในตาราง users เรียบร้อยแล้ว ทดสอบการลบ DELETE กลุ่ม &#8216;IT&#8217; ออกจาก table &#8216;groups&#8217;</p>
<pre>mysql&gt; <strong>DELETE FROM groups WHERE group_id='103';
</strong><span style="color: #ff0000;">ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails
</span>(`test_db`.`users`, CONSTRAINT `users_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `groups` (`group_id`))</pre>
<p>ข้อมูลกลุ่ม &#8216;IT&#8217; ยังอยู่ใน table &#8216;groups&#8217;</p>
<pre>mysql&gt; <strong>SELECT * FROM groups;
</strong>+----------+------------+
| group_id | group_name |
+----------+------------+
|      101 | Accounting |
|      102 | Engineer   |
|      103 | IT         |
|      104 | Manager    |
+----------+------------+
4 rows in set (0.00 sec)</pre>
<p>เราไม่สามารถลบ group &#8216;IT&#8217; ได้ เนื่องจากมีการอ้างอิงจาก table &#8216;users&#8217;</p>
<p>หากต้องการจะลบ ต้องแก้ไขข้อมูลที่มีการอ้างอิงมายัง group &#8216;IT&#8217; นี้ (group_id=103) เช่นในที่นี้ต้องเปลี่ยน group_id ของ &#8216;Mr.D&#8217; ไปเป็นกลุ่มอื่น เช่นเปลี่ยนเป็น กลุ่ม &#8216;Engineer&#8217;</p>
<p>ตรวจสอบว่าใครอยู่ group &#8216;IT&#8217; บ้าง</p>
<pre>mysql&gt; <strong>SELECT * FROM users WHERE group_id=103;
</strong>+---------+----------+-----------+
| user_id | group_id | user_name |
+---------+----------+-----------+
|     504 |      103 | Mr.D      |
+---------+----------+-----------+
1 row in set (0.00 sec)</pre>
<p>เปลี่ยนกลุ่มของ &#8216;MR.D&#8217; เป็น Engineer</p>
<pre>mysql&gt; <strong>UPDATE users SET group_id=102 WHERE user_id=504;
</strong>Query OK, 0 rows affected (0.00 sec)
Rows matched: 1  Changed: 0  Warnings: 0</pre>
<p>ตรวจสอบว่าใครอยู่ group &#8216;IT&#8217; อีกครั้ง</p>
<pre>mysql&gt; <strong>SELECT * FROM users WHERE group_id=103;
</strong>Empty set (0.00 sec)</pre>
<p>ทดสอบการลบกลุ่ม IT</p>
<pre>mysql&gt; <strong>DELETE FROM groups WHERE group_id=103;
</strong>Query OK, 1 row affected (0.00 sec)</pre>
<p>ครั้งนี้จะสามารถลบได้แล้ว เพราะไม่มี user คนไหนอยู่ในกลุ่มนี้แล้ว</p>
<h4>การ INSERT, UPDATE ข้อมูล</h4>
<p>จะด้วยความผิดพลาดของโปรแกรมหรือตั้งใจ สมมติเราเพิ่ม users ใหม่ แล้วตั้ง group_id=109 ซึ่งไม่มีอยู่ใน table &#8216;groups&#8217;</p>
<pre>mysql&gt; <strong>INSERT INTO users (user_id, group_id, user_name) VALUES (506, <span style="color: #ff0000;">109</span>, 'Mr.X');
</strong><span style="color: #ff0000;">ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails
</span>(`test_db`.`users`, CONSTRAINT `users_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `groups` (`group_id`))</pre>
<p>เราจะไม่สามารถ INSERT ข้อมูลแบบนี้ได้ ต้องไปสร้าง group_id 109 ใน table &#8216;groups&#8217; ก่อน</p>
<p>เช่นเดียวกัน เราไม่สามารถ UPDATE ข้อมูลที่ไม่ถูกต้องได้</p>
<pre>mysql&gt; <strong>UPDATE users SET group_id=109 WHERE user_id=505;
</strong><span style="color: #ff0000;">ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails
</span>(`test_db`.`users`, CONSTRAINT `users_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `groups` (`group_id`))</pre>
<h4>การ DROP TABLE</h4>
<p>หากยังมีการอ้างอิงฟิลด์ข้อมูลอยู่ เราไม่สามารถ DROP TABLE ที่ยังมีข้อมูลอ้างอิงอยู่ได้ เช่นในที่นี้เราไม่สามารถ DROP TABLE groups ได้</p>
<pre>mysql&gt; <strong>DROP TABLE groups;
</strong><span style="color: #ff0000;">ERROR 1217 (23000): Cannot delete or update a parent row: a foreign key constraint fails</span></pre>
<p>ถึงแม้ไม่มีข้อมูล rows ใดเลยใน users ก็ไม่สามารถ DROP TABLE groups ได้</p>
<pre>mysql&gt; <strong>DELETE FROM users;
</strong>Query OK, 5 rows affected (0.00 sec)</pre>
<pre>mysql&gt; <strong>DROP TABLE groups;
</strong>ERROR 1217 (23000): Cannot delete or update a parent row: a foreign key constraint fails</pre>
<h4>ข้อมูลอ้างอิง</h4>
<ul>
<li><a href="http://spalinux.com/2010/01/creating_mysql_foreign_key_constraints">การสร้าง FOREIGN KEY Constraints ใน MySQL</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://spalinux.com/2010/01/testing_mysql_foreign_key_constraints/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>การสร้าง FOREIGN KEY Constraints ใน MySQL</title>
		<link>http://spalinux.com/2010/01/creating_mysql_foreign_key_constraints</link>
		<comments>http://spalinux.com/2010/01/creating_mysql_foreign_key_constraints#comments</comments>
		<pubDate>Sat, 23 Jan 2010 09:22:39 +0000</pubDate>
		<dc:creator>editor</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[mysql constraints]]></category>
		<category><![CDATA[mysql foreign key]]></category>

		<guid isPermaLink="false">http://spalinux.com/?p=1053</guid>
		<description><![CDATA[ส่วนใหญ่แล้วการออกแบบฐานข้อมูลจะมีการใช้บางฟิลด์ข้อมูล เพื่อเชื่อมโยงความสัมพันธ์ระหว่าง table ทำให้ต้องมีการคำนึงถึงเวลา เพิ่ม แก้ไข หรือ ลบฟิลด์ที่ใช้เชื่อมนั้น ไม่เช่นนั้นข้อมูลในฐานข้อมูลอาจมีปัญหาได้
MySQL สนับสนุนคุณสมบัติการใช้ FOREIGN KEY Constraints เพื่อแก้ไขปัญหานี้ได้ แต่ต้องใช้ table เป็นแบบ InnoDB ในบทความนี้ขออธิบายปัญหาที่เกิดขึ้น พร้อมยกตัวอย่างวิธีการใช้ FOREIGN KEY Constraints เพื่อป้องกันปัญหาได้

ตัวอย่างเช่น ต้องการสร้างฐานข้อมูลสำหรับเก็บชื่อ users และแต่ละคนเป็นสมาชิกได้ 1 กลุ่มจากตาราง groups เริ่มต้นออกแบบ table ง่ายๆ ได้ดังนี้
mysql&#62; CREATE TABLE groups (
 group_id     INT UNSIGNED NOT NULL,
 group_name   VARCHAR(255),
 PRIMARY KEY    (group_id)
);
mysql&#62; CREATE TABLE users (
 user_id      INT UNSIGNED NOT NULL,
 group_id     INT UNSIGNED [...]]]></description>
			<content:encoded><![CDATA[<p>ส่วนใหญ่แล้วการออกแบบฐานข้อมูลจะมีการใช้บางฟิลด์ข้อมูล เพื่อเชื่อมโยงความสัมพันธ์ระหว่าง table ทำให้ต้องมีการคำนึงถึงเวลา เพิ่ม แก้ไข หรือ ลบฟิลด์ที่ใช้เชื่อมนั้น ไม่เช่นนั้นข้อมูลในฐานข้อมูลอาจมีปัญหาได้</p>
<p>MySQL สนับสนุนคุณสมบัติการใช้ FOREIGN KEY Constraints เพื่อแก้ไขปัญหานี้ได้ แต่ต้องใช้ table เป็นแบบ InnoDB ในบทความนี้ขออธิบายปัญหาที่เกิดขึ้น พร้อมยกตัวอย่างวิธีการใช้ FOREIGN KEY Constraints เพื่อป้องกันปัญหาได้</p>
<p><span id="more-1053"></span></p>
<p>ตัวอย่างเช่น ต้องการสร้างฐานข้อมูลสำหรับเก็บชื่อ users และแต่ละคนเป็นสมาชิกได้ 1 กลุ่มจากตาราง groups เริ่มต้นออกแบบ table ง่ายๆ ได้ดังนี้</p>
<pre>mysql&gt; <strong>CREATE TABLE groups (
 group_id     INT UNSIGNED NOT NULL,
 group_name   VARCHAR(255),
 PRIMARY KEY    (group_id)
);</strong></pre>
<pre>mysql&gt; <strong>CREATE TABLE users (
 user_id      INT UNSIGNED NOT NULL,
 group_id     INT UNSIGNED NOT NULL,
 user_name    VARCHAR(255),
 PRIMARY KEY    (user_id)
);</strong></pre>
<p>ใส่ข้อมูลทดสอบดังนี้</p>
<pre>mysql&gt; <strong>INSERT INTO groups (group_id, group_name) VALUES
 (101, 'Accounting'),
 (102, 'Engineer'),
 (103, 'IT'),
 (104, 'Manager');</strong></pre>
<pre>mysql&gt; <strong>INSERT INTO users (user_id, group_id, user_name) VALUES
 (501, 101, 'Ms.A'),
 (502, 102, 'Ms.B'),
 (503, 102, 'Mr.C'),
 (504, 103, 'Mr.D'),
 (505, 104, 'Mr.E');</strong></pre>
<p>จากฐานข้อมูลตัวอย่าง เราใช้ฟิลด์ group_id ในการเชื่อมโยงความสัมพันธ์ระหว่าง groups และ users เพื่อระบุว่า แต่ละ users อยู่ใน group ใด</p>
<p>หากมีการแก้ไขข้อมูล เช่นต้องการลบ (DELETE) ข้อมูล group ที่ชื่อ &#8216;IT&#8217; ออกจากฐานข้อมูล หากไม่มีวิธีการตรวจสอบ ไปลบแค่จากตาราง &#8216;groups&#8217; จะทำให้ ข้อมูลของ &#8216;Mr.D&#8217; ในตาราง &#8216;users&#8217; มีปัญหาทันที เพราะไม่สามารถอ้างอิงกลับมายังชื่อ group ได้</p>
<p>โดยดีฟอลต์ การสร้าง table ใน MySQL หากไม่มีการระบุชนิด ในคำสั่ง &#8216;CREATE TABLE&#8217; ตารางที่สร้างได้จะเป็นแบบ MyISAM ซึ่งไม่สามารถสร้าง FOREIGN KEY ได้</p>
<p>สามารถใช้คำสั่ง &#8216;SHOW ENGINES&#8217; ใน mysql เพื่อตรวจสอบชนิดของ table ที่สร้างได้</p>
<pre>mysql&gt; <strong>SHOW ENGINES;
</strong>+------------+---------+------------------------------------------------------------+--------------+------+------------+
| Engine     | Support | Comment                                                    | Transactions | XA   | Savepoints |
+------------+---------+------------------------------------------------------------+--------------+------+------------+
| ndbcluster | NO      | Clustered, fault-tolerant tables                           | NULL         | NULL | NULL       |
| MRG_MYISAM | YES     | Collection of identical MyISAM tables                      | NO           | NO   | NO         |
| CSV        | YES     | CSV storage engine                                         | NO           | NO   | NO         |
| <strong><span style="color: #0000ff;">MyISAM</span>     </strong>| <strong><span style="color: #0000ff;">DEFAULT</span> </strong>| Default engine as of MySQL 3.23 with great performance     | NO           | NO   | NO         |
| <strong><span style="color: #0000ff;">InnoDB</span></strong>     | <strong><span style="color: #0000ff;">YES</span></strong>     | Supports transactions, row-level locking, and <strong><span style="color: #0000ff;">foreign keys</span></strong> | YES          | YES  | YES        |
| MEMORY     | YES     | Hash based, stored in memory, useful for temporary tables  | NO           | NO   | NO         |
+------------+---------+------------------------------------------------------------+--------------+------+------------+</pre>
<p>ถ้าจะใช้ FOREIGN KEY ได้นั้น table ที่มีการอ้างอิงกันทั้งหมด ต้องเป็นชนิด InnoDB คือต้องระบุออปชั่น ENGINE=InnoDB เวลาสร้าง table</p>
<p>เมื่อสร้างเป็น InnoDB แล้ว ระบุฟิลด์ที่ต้องการตรวจสอบ constraints ใน table ที่ใช้อ้างอิงไปยัง table อื่น</p>
<p>เช่นในที่นี้เราต้องการให้ table &#8216;users&#8217; ใช้ฟิลด์ชื่อ group_id เพื่ออ้างอิงไปยัง table &#8216;groups&#8217; เราต้องระบุ FOREIGN KEY ใน table &#8216;users&#8217;</p>
<p>วิธีการระบุการอ้างอิง FOREIGN KEY ฟิลด์ &#8216;group_id&#8217; จาก table &#8216;groups&#8217;</p>
<pre><span style="color: #0000ff;"><strong>FOREIGN KEY (group_id) REFERENCES groups(group_id)</strong></span></pre>
<p>วิธีการเปลี่ยน table จาก MyISAM ให้เป็น InnoDB และเพิ่ม FOREIGN KEY ทำได้ 2 วิธี</p>
<p> 1. ใช้คำสั่ง &#8216;ALTER TABLE&#8217; เพื่อแก้ไข<br />
 2. ใช้คำสั่ง &#8216;DROP TABLE&#8217; ทิ้งไปแล้วสร้างใหม่ แต่ข้อมูลที่มีอยู่จะหายหมด</p>
<h4>ใช้คำสั่ง ALTER TABLE เพื่อเปลี่ยนชนิดเป็น InnoDB</h4>
<p>เราสามารถใช้คำสั่ง &#8216;ALTER TABLE&#8217; เพื่อเปลี่ยนชนิดของ table หรือแก้ไขฟิลด์ต่างๆ ได้</p>
<p>การใช้คำสั่ง ALTER TABLE เพื่อเปลี่ยนชนิด table เป็นแบบ InnoDB</p>
<pre>mysql&gt; <strong>ALTER TABLE groups ENGINE=InnoDB;
</strong>Query OK, 4 rows affected (0.01 sec)
Records: 4  Duplicates: 0  Warnings: 0</pre>
<pre>mysql&gt; <strong>ALTER TABLE users ENGINE=InnoDB;
</strong>Query OK, 5 rows affected (0.01 sec)
Records: 5  Duplicates: 0  Warnings: 0</pre>
<p>เพิ่ม FOREIGN KEY ใน table &#8216;users&#8217;</p>
<pre>mysql&gt; <strong>ALTER TABLE `users` ADD FOREIGN KEY (group_id) REFERENCES groups(group_id);
</strong>Query OK, 5 rows affected (0.01 sec)
Records: 5  Duplicates: 0  Warnings: 0</pre>
<p>หมายเหตุ ต้องดูผลลัพธ์การใช้คำสั่ง ALTER TABLE ด้วย ว่าการเปลี่ยนแปลง table สำเร็จหรือไม่</p>
<h4>ลบแล้วสร้าง TABLE ใหม่แบบ InnoDB และใช้ FOREIGN KEY</h4>
<p>ใช้คำสั่ง DROP TABLE เพื่อลบ table &#8216;users&#8217;</p>
<pre>mysql&gt; <strong>DROP TABLE users;
</strong>mysql&gt; <strong>DROP TABLE groups;</strong></pre>
<p>ใช้คำสั่ง CREATE TABLE เพื่อสร้าง table ใหม่ แล้ว ใส่ข้อมูลลงไปเหมือนเดิม</p>
<pre>mysql&gt; <strong>CREATE TABLE groups (
 group_id     INT UNSIGNED NOT NULL,
 group_name   VARCHAR(255),
 PRIMARY KEY    (group_id)
) <span style="color: #0000ff;">ENGINE=InnoDB</span>;</strong></pre>
<pre>mysql&gt; <strong>INSERT INTO groups (group_id, group_name) VALUES
 (101, 'Accounting'),
 (102, 'Engineer'),
 (103, 'IT'),
 (104, 'Manager');</strong></pre>
<pre>mysql&gt; <strong>CREATE TABLE users (
 user_id      INT UNSIGNED NOT NULL,
 group_id     INT UNSIGNED NOT NULL,
 user_name    VARCHAR(255),
 PRIMARY KEY    (user_id),
<span style="color: #0000ff;"> FOREIGN KEY (group_id) REFERENCES groups(group_id)
</span>) <span style="color: #0000ff;">ENGINE=InnoDB;</span></strong></pre>
<pre>mysql&gt; <strong>INSERT INTO users (user_id, group_id, user_name) VALUES
 (501, 101, 'Ms.A'),
 (502, 102, 'Ms.B'),
 (503, 102, 'Mr.C'),
 (504, 103, 'Mr.D'),
 (505, 104, 'Mr.E');</strong></pre>
<p>สังเกตสิ่งที่เพิ่มขึ้น</p>
<h4>ข้อมูลอ้างอิง</h4>
<ul>
<li><a href="http://dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html" target="_blank">MySQL 5.1 Reference Manual :: 13.6.4.4 FOREIGN KEY Constraints</a></li>
<li><a href="http://spalinux.com/2010/01/testing_mysql_foreign_key_constraints">ทดสอบ FOREIGN KEY Constraints ใน MySQL</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://spalinux.com/2010/01/creating_mysql_foreign_key_constraints/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>วิธีการใช้คำสั่ง wget</title>
		<link>http://spalinux.com/2010/01/using_wget</link>
		<comments>http://spalinux.com/2010/01/using_wget#comments</comments>
		<pubDate>Fri, 22 Jan 2010 08:04:48 +0000</pubDate>
		<dc:creator>editor</dc:creator>
				<category><![CDATA[Console]]></category>
		<category><![CDATA[Proxy]]></category>
		<category><![CDATA[Web Server]]></category>
		<category><![CDATA[wget]]></category>

		<guid isPermaLink="false">http://spalinux.com/?p=1047</guid>
		<description><![CDATA[wget เป็นโปรแกรมที่ใช้เพื่อดาวน์โหลดไฟล์จากเว็บไซต์ได้ ในรูปแบบ text console วิธีการใช้งานก็ง่ายคือรันคำสั่ง wget ตามด้วย URL ที่ต้องการดาวน์โหลด ผลลัพธ์ที่ได้จะถูกบันทึกเป็นไฟล์ของเว็บเพจหน้านั้นๆ

รูปแบบการใช้งาน
$ wget [option]... [URL]...
ตัวอย่างเช่น ต้องการดาวน์โหลดเว็บเพจหน้าแรกของ www.google.co.th
$ wget 'http://www.google.co.th'
--13:52:23--  http://www.google.co.th/
           =&#62; `index.html'
Resolving www.google.co.th... 72.14.203.147, 72.14.203.103, 72.14.203.104, ...
Connecting to www.google.co.th&#124;72.14.203.147&#124;:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
    [  &#60;=&#62;                                                                                ] 6,726         11.96K/s
13:52:24 (11.96 KB/s) - `index.html' saved [6726]
จากตัวอย่าง ผลลัพธ์ที่ได้จะถูกบันทึกเป็นชื่อ index.html
หมายเหตุ แนะนำให้ใส่เครื่องหมายคำพูด &#8216;  คลอบ URL เพราะบางตัวอักษรอาจมีความหมายใน [...]]]></description>
			<content:encoded><![CDATA[<p>wget เป็นโปรแกรมที่ใช้เพื่อดาวน์โหลดไฟล์จากเว็บไซต์ได้ ในรูปแบบ text console วิธีการใช้งานก็ง่ายคือรันคำสั่ง wget ตามด้วย URL ที่ต้องการดาวน์โหลด ผลลัพธ์ที่ได้จะถูกบันทึกเป็นไฟล์ของเว็บเพจหน้านั้นๆ</p>
<p><span id="more-1047"></span></p>
<h4>รูปแบบการใช้งาน</h4>
<pre>$ <strong>wget</strong> [option]... [URL]...</pre>
<p>ตัวอย่างเช่น ต้องการดาวน์โหลดเว็บเพจหน้าแรกของ www.google.co.th</p>
<pre>$ <strong>wget 'http://www.google.co.th'
</strong>--13:52:23--  http://www.google.co.th/
           =&gt; `index.html'
Resolving www.google.co.th... 72.14.203.147, 72.14.203.103, 72.14.203.104, ...
Connecting to www.google.co.th|72.14.203.147|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]</pre>
<pre>    [  &lt;=&gt;                                                                                ] 6,726         11.96K/s</pre>
<pre>13:52:24 (11.96 KB/s) - `<span style="color: #0000ff;">index.html</span>' saved [6726]</pre>
<p>จากตัวอย่าง ผลลัพธ์ที่ได้จะถูกบันทึกเป็นชื่อ index.html</p>
<p>หมายเหตุ แนะนำให้ใส่เครื่องหมายคำพูด &#8216;  คลอบ URL เพราะบางตัวอักษรอาจมีความหมายใน SHELL</p>
<pre>$ <strong>cat index.html
</strong>&lt;!doctype html&gt;&lt;html&gt;&lt;head&gt;&lt;meta http-equiv="content-type" content="text/html; charset=windows-874"&gt;&lt;title&gt;Google&lt;/title&gt;
...</pre>
<p>ระบุออปชั่น &#8216;&#8211;help&#8217; เพื่อดูวิธีการใช้งาน พร้อมทั้งออปชั่นต่างๆ</p>
<pre>$ <strong>wget --help
</strong>GNU Wget 1.10.2 (Red Hat modified), a non-interactive network retriever.
Usage: wget [OPTION]... [URL]...</pre>
<pre>Mandatory arguments to long options are mandatory for short options too.</pre>
<pre>Startup:
  -V,  --version           display the version of Wget and exit.
  -h,  --help              print this help.
  -b,  --background        go to background after startup.
  -e,  --execute=COMMAND   execute a `.wgetrc'-style command.</pre>
<p>ในบทความนี้ขอแนะนำการใช้ออปชั่นที่ผู้เขียนใช้บ่อยๆ</p>
<h4>ดูรายละเอียดการโหลด (debug)</h4>
<p>ระบุออปชั่น &#8216;-d&#8217; เพื่อดูรายละเอียดการดาวน์โหลด เช่นดู HTTP Header, Protocol, Cookie ที่เกิดขึ้นในการดาวน์โหลด</p>
<pre>$ <strong>wget -d 'http://www.google.co.th'
</strong>DEBUG output created by Wget 1.10.2 (Red Hat modified) on linux-gnu.</pre>
<pre>--14:16:24--  http://www.google.co.th/
           =&gt; `index.html'
Resolving www.google.co.th... 72.14.203.105, 72.14.203.106, 72.14.203.99, ...
Caching www.google.co.th =&gt; 72.14.203.105 72.14.203.106 72.14.203.99 72.14.203.104 72.14.203.103 72.14.203.147
Connecting to www.google.co.th|72.14.203.105|:80... connected.
Created socket 3.
Releasing 0x000000000083d390 (new refcount 1).</pre>
<pre>---request begin---
GET / HTTP/1.0
User-Agent: Wget/1.10.2 (Red Hat modified)
Accept: */*
Host: www.google.co.th
Connection: Keep-Alive</pre>
<pre>---request end---
HTTP request sent, awaiting response...
---response begin---
HTTP/1.0 200 OK
Date: Fri, 22 Jan 2010 07:16:29 GMT
Expires: -1
Cache-Control: private, max-age=0
Content-Type: text/html; charset=windows-874
Set-Cookie: PREF=ID=79a6955a36392a2d:TM=1264144589:LM=1264144589:S=c99kK7cOeBwCp4KG; expires=Sun, 22-Jan-2012 07:16:29 GMT; path                                             =/;</pre>
<pre>domain=.google.co.th
Set-Cookie: NID=31=h8-gos7iGB-MXzlXOo4C1_CRqzSNE6wu5Os2WBu6C-jm7tPhrlj4kJp1aiENCM66f388IScBzce4Q-6x7rwbfxUUbp2DGAIcxXu1zwSGy6zKH                                            </pre>
<pre>cjUQ2_59hiym_wuaRt2; expires=Sat, 24-Jul-2010 07:16:29 GMT; path=/; domain=.google.co.th; HttpOnly
Server: gws
X-XSS-Protection: 0</pre>
<pre>---response end---
200 OK
cdm: 1 2 3 4 5 6 7 8
Stored cookie google.co.th -1 (ANY) / &lt;permanent&gt; &lt;insecure&gt; [expiry 2012-01-22 14:16:29] PREF ID=79a6955a36392a2d:TM=1264144589                                            </pre>
<pre>:LM=1264144589:S=c99kK7cOeBwCp4KG
cdm: 1 2 3 4 5 6 7 8
Stored cookie google.co.th -1 (ANY) / &lt;permanent&gt; &lt;insecure&gt; [expiry 2010-07-24 14:16:29] NID 31=h8-gos7iGB-MXzlXOo4C1_CRqzSNE6w                                            </pre>
<pre>u5Os2WBu6C-jm7tPhrlj4kJp1aiENCM66f388IScBzce4Q-6x7rwbfxUUbp2DGAIcxXu1zwSGy6zKHcjUQ2_59hiym_wuaRt2
Length: unspecified [text/html]</pre>
<pre>    [  &lt;=&gt;                                                                                ] 6,702          6.21K/s</pre>
<pre>Closed fd 3
14:16:31 (6.20 KB/s) - `index.html' saved [6702]</pre>
<h4>ดาวน์โหลดต่อไฟล์ (continue)</h4>
<p>สามารถดาวน์โหลดไฟล์ต่อจากที่ดาวน์โหลดยังไม่ครบได้</p>
<p>เช่นต้องการดาวน์โหลดไฟล์ iso ที่มีขนาดใหญ่มาก แล้วดาวน์โหลดครั้งแรกยังไม่ครบ</p>
<pre>$ <strong>wget 'http://www.mirror.in.th/osarchive/fedora/releases/11/Live/x86_64/Fedora-11-x86_64-Live.iso'
</strong>--14:09:51--  http://www.mirror.in.th/osarchive/fedora/releases/11/Live/x86_64/Fedora-11-x86_64-Live.iso
           =&gt; `Fedora-11-x86_64-Live.iso'
Resolving <a href="http://www.mirror.in.th/">www.mirror.in.th</a>... 61.7.253.242
Connecting to www.mirror.in.th|61.7.253.242|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 724,097,024 (691M) [application/octet-stream]</pre>
<pre> 0% [                                                                                     ] 1,090,066     87.82K/s  ETA 2:13:52</pre>
<p>หมายเหตุ ในระหว่างการดาวน์โหลด หากต้องการยกเลิกให้กด [Ctrl-C]</p>
<p>ครั้งแรกดาวน์โหลดไฟล์ได้แค่ 1 Meg กว่าๆ</p>
<pre>$ <strong>ls -l
</strong>total 1080
-rw-r--r-- 1 user1  users  1098754 2010-01-22 14:10 Fedora-11-x86_64-Live.iso</pre>
<p>ถ้าต้องการดาวน์โหลดต่อ ต้องระบุออปชั่น &#8216;-c&#8217;</p>
<pre>$ <strong>wget -c 'http://www.mirror.in.th/osarchive/fedora/releases/11/Live/x86_64/Fedora-11-x86_64-Live.iso'
</strong>--14:11:46--  http://www.mirror.in.th/osarchive/fedora/releases/11/Live/x86_64/Fedora-11-x86_64-Live.iso
           =&gt; `Fedora-11-x86_64-Live.iso'
Resolving www.mirror.in.th... 61.7.253.242
Connecting to www.mirror.in.th|61.7.253.242|:80... connected.
HTTP request sent, awaiting response... 206 <span style="color: #0000ff;">Partial Content</span>
Length: 724,097,024 (691M), 722,998,270 (690M) remaining [application/octet-stream]</pre>
<pre> 0% [                                                                                     ] 1,401,045     94.59K/s  ETA 2:04:50</pre>
<pre>$ <strong>ls -l
</strong>total 1384
-rw-r--r-- 1 user1  users  1409733 2010-01-22 14:11 Fedora-11-x86_64-Live.iso</pre>
<h4>จำกัดความเร็วการโหลด</h4>
<p>ต้องการโหลดไฟล์แต่ไม่ต้องการเบียดบังความเร็วการใช้อินเตอร์เน็ตจากคนอื่นมากเกินไป เราสามารถจำกัดความเร็วในการโหลดของเราได้ ด้วยออปชั่น &#8216;&#8211;limit-rate&#8217;</p>
<p>เช่นต้องการจำกัดไว้ที่ 10 KBytes/s</p>
<pre>$ <strong>wget --limit-rate 10000 'http://www.mirror.in.th/osarchive/fedora/releases/11/Live/x86_64/Fedora-11-x86_64-Live.iso'
</strong>--14:25:14--  http://www.mirror.in.th/osarchive/fedora/releases/11/Live/x86_64/Fedora-11-x86_64-Live.iso
           =&gt; `Fedora-11-x86_64-Live.iso'
Resolving www.mirror.in.th... 61.7.253.242
Connecting to www.mirror.in.th|61.7.253.242|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 724,097,024 (691M) [application/octet-stream]</pre>
<pre> 0% [                                                                                     ] 62,618         9.77K/s ETA 20:07:01</pre>
<p>หมายเหตุ หน่วยของออปชั่น &#8216;&#8211;limit-rate&#8217; เป็น bytes per second</p>
<h4>โหลดผ่าน proxy</h4>
<p>หากต้องใช้ proxy ในการโหลด ต้องมีการระบุตัวแปร &#8216;http_proxy&#8217; ไว้ใน shell ก่อนรันคำสั่ง เช่น IP ของ proxy คือ 192.168.1.1 และพอร์ต proxy คือ 3128 ถ้าใช้ BASH สามารถทำได้โดย</p>
<pre>$ <strong>export http_proxy=http://192.168.1.1:3128</strong></pre>
<p>ใช้คำสั่ง wget พร้อมระบุออปชั่น &#8216;&#8211;proxy&#8217; เพื่อให้โหลดผ่าน proxy</p>
<pre>$ <strong>wget --proxy 'http://www.mirror.in.th/osarchive/fedora/releases/11/Live/x86_64/Fedora-11-x86_64-Live.iso'
</strong>--2010-01-22 14:30:26--  http://www.mirror.in.th/osarchive/fedora/releases/11/Live/x86_64/Fedora-11-x86_64-Live.iso
Connecting to 192.168.1.1:3128... connected.
Proxy request sent, awaiting response... 200 OK
Length: 724097024 (691M) [application/octet-stream]
Saving to: `Fedora-11-x86_64-Live.iso'</pre>
<pre> 0% [                                                                                     ] 63,434      96.4K/s</pre>
<p>แต่ถ้า proxy ต้องระบุ user, password ด้วย จะขึ้น error ดังนี้</p>
<pre>$ <strong>wget --proxy  'http://www.mirror.in.th/osarchive/fedora/releases/11/Live/x86_64/Fedora-11-x86_64-Live.iso'
</strong>--2010-01-22 14:31:06--  http://www.mirror.in.th/osarchive/fedora/releases/11/Live/x86_64/Fedora-11-x86_64-Live.iso
Connecting to 192.168.1.1:3128... connected.
Proxy request sent, awaiting response... 407 Proxy Authentication Required
2010-01-22 14:31:06 ERROR 407: Proxy Authentication Required.</pre>
<pre>ใช้ออปชั่น '--proxy-user' และ '--proxy-password' เพื่อระบุ user, password ในการใช้ proxy</pre>
<pre>$ <strong>wget --proxy-user=prxuser --proxy-password=prx1234  'http://www.mirror.in.th/osarchive/fedora/releases/11/Live/x86_64/Fedora-11-x86_64-Live.iso'
</strong>--2010-01-22 14:30:26--  http://www.mirror.in.th/osarchive/fedora/releases/11/Live/x86_64/Fedora-11-x86_64-Live.iso
Connecting to 192.168.1.1:3128... connected.
Proxy request sent, awaiting response... 200 OK
Length: 724097024 (691M) [application/octet-stream]
Saving to: `Fedora-11-x86_64-Live.iso'</pre>
<pre> 0% [                                                                                     ] 63,434      96.4K/s</pre>
<h4>ไฟล์คอนฟิก .wgetrc</h4>
<p>แทนที่จะต้องระบุออปชั่น proxy ทุกครั้ง สามารถสร้างเป็นไฟล์คอนฟิกสำหรับใช้คำสั่ง wget โดยสร้างไฟล์ชื่อ .wgetrc (มีเครื่องหมายจุดนำหน้าชื่อไฟล์ด้วย) ไว้ใน HOME ของผู้ใช้งาน</p>
<pre>$ <strong>cat ~/.wgetrc
</strong>http_proxy=http://192.168.1.1:3128/
proxy_user=prxuser
proxy_password=prx1234</pre>
<p>หลังจากสร้างไฟล์คอนฟิก .wgetrc แล้ว เวลาใช้คำสั่ง wget ก็ไม่ต้องระบุออปชั่นใดๆ อีก</p>
<pre>$ <strong>wget  'http://www.mirror.in.th/osarchive/fedora/releases/11/Live/x86_64/Fedora-11-x86_64-Live.iso'
</strong>--2010-01-22 14:37:46--  http://www.mirror.in.th/osarchive/fedora/releases/11/Live/x86_64/Fedora-11-x86_64-Live.iso
Connecting to 192.168.1.1:3128... connected.
Proxy request sent, awaiting response... 200 OK
Length: 724097024 (691M) [application/octet-stream]
Saving to: `Fedora-11-x86_64-Live.iso.1'</pre>
<pre> 0% [                                                                                     ] 80,810      95.8K/s</pre>
<h4>ข้อมูลอ้างอิง</h4>
<ul>
<li><a href="http://www.gnu.org/software/wget/" target="_blank">GNU Wget</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://spalinux.com/2010/01/using_wget/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
