<body><script type="text/javascript"> function setAttributeOnload(object, attribute, val) { if(window.addEventListener) { window.addEventListener("load", function(){ object[attribute] = val; }, false); } else { window.attachEvent('onload', function(){ object[attribute] = val; }); } } </script> <iframe src="http://www.blogger.com/navbar.g?targetBlogID=7355927&amp;blogName=Poonlap%27s+Linux+blog&amp;publishMode=PUBLISH_MODE_BLOGSPOT&amp;navbarType=BLUE&amp;layoutType=CLASSIC&amp;searchRoot=http%3A%2F%2Fpoonlap.blogspot.com%2Fsearch&amp;blogLocale=en_US&amp;homepageUrl=http%3A%2F%2Fpoonlap.blogspot.com%2F" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" height="30px" width="100%" id="navbar-iframe" allowtransparency="true" title="Blogger Navigation and Search"></iframe> <div></div>
 Poonlap's Linux blog  ใช้ซอฟต์แวร์เสรี, มีทางเลือก, ประเทืองปัญญา, พึ่งพาตนเอง.
 
      « Home

เนื้อหาที่ผ่านมา

ลาก่อน blogspot
ใช้ ange-ftp กับ emacs
บันทึกด้วย script
ปีใหม่แล้วเวลาช้าลง 1 วินาที
เปรียบ Java กับ Ruby (ด้วยความหนาของหนังสือ)
แปลคำศัพท์ด้วย Longdo dictionary จาก Firefox
Object Oriented ใน ruby
พวกคำย่อ
ruby เบื้องต้น
del.icio.us/poonlap
 
      เนื้อหาในอดีต
06/01/2004 - 07/01/2004
07/01/2004 - 08/01/2004
08/01/2004 - 09/01/2004
09/01/2004 - 10/01/2004
10/01/2004 - 11/01/2004
11/01/2004 - 12/01/2004
12/01/2004 - 01/01/2005
01/01/2005 - 02/01/2005
02/01/2005 - 03/01/2005
03/01/2005 - 04/01/2005
04/01/2005 - 05/01/2005
05/01/2005 - 06/01/2005
06/01/2005 - 07/01/2005
07/01/2005 - 08/01/2005
08/01/2005 - 09/01/2005
09/01/2005 - 10/01/2005
10/01/2005 - 11/01/2005
11/01/2005 - 12/01/2005
12/01/2005 - 01/01/2006
01/01/2006 - 02/01/2006
02/01/2006 - 03/01/2006
03/01/2006 - 04/01/2006
 
      เชิ่อมโยง

รูปประกอบ (Flickr)
โค้ด
รูปประกอบ (อดีต)
deli.icio.us/poonlap

Thai Linux Working group
TLWG Planet
Blognone
Home at LTN
Bact's blog
Hui blog
Theppitak's blog
Noi's life & thoughts
Kitty.in.th
Sf-alpha
Vee blog
too - blogin'
Mk's blog
Pok's blogger
Vmlinix blog
Sothorn's Web log
คุณอุทัย
DrRider's Blog
Donga's memories

This page is powered by Blogger. Isn't yours?

Creative Commons License

ธนาบุตรโฟโต้บุ๊ค
อัดรูปดิจิตอล ทำสมุดภาพของคุณเอง
รอรับได้. ท่องเที่ยว แต่งงาน ฯลฯ
www.tanabutr.co.th/photobook

Qt way - 3 นาทีกับการเขียนโปรแกรม GUI ง่ายๆบนลินุกซ์

ที่อยู่ใหม่ของ Poonlap's Linux blog : http://mm.co.th/poonlap

ว่าจะไม่เขียน Blog ต่อแล้วแต่อดไม่ได้. เขียนหน่อยแล้วกัน, เป็นการแบ่งความรู้สำหรับคนที่ต้องการเริ่มเขียนโปรแกรมด้วย Qt. อันนี้พอจะเป็นจุดเริ่มต้น (きっかけ) ได้ครับ.

ตัวอย่างต่อไปนี้เป็นการเขียนโปรแกรมด้วยภาษา C++ โดยใช้ Qt library. ในระบบที่ต้องการลองต้องมี Qt library 3.x อยู่. ถ้าเป็น Gentoo ก็ติดตั้ง Qt ได้ด้วยคำสั่ง emerge.

# USE=doc emerge qt
อันนี้ใช้ USE=doc เพื่อที่จะติดตั้งเอกสารด้วย.

โปรแกรมตัวอย่าง Hello Qt

โปรแกรมตัวอย่างใช้บรรณาธิกรณ์อะไรเขียนก็ได้. ให้มีชื่อเป็น hello.cpp แล้วเก็บไว้ในไดเรกทอรีที่ชื่อ hello ครับ.
     1  #include <qapplication.h>
     2  #include <qpushbutton.h>
     3
     4  int main( int argc, char* argv[])
     5  {
     6          QApplication app(argc, argv);
     7          QPushButton *button = new QPushButton("Hello Qt!", 0);
     8          button->show();
     9          app.setMainWidget( button);
    10          button->connect( button, SIGNAL(clicked()), button, SLOT(close()));
    11          app.exec();
    12  }
อธิบายทีละบรรทัดเลยแล้วกัน. บรรทัดที่ 1 เป็นไฟล์ header สำหรับการสร้าง Qt application. ส่วนบรรทัดที่สองเป็นไฟล์ header สำหรับใช้วิดเจด (widget) QPushButton.

บรรทัดที่ 4 เริ่มฟังก์ชัน main เหมือนโปรแกรม C/C++ ทั่วไป. บรรทัดที่ 6 สร้าง instance ของ QApplication ชื่อโดยใส่อาร์กิวเมนต์เป็น argc และ argv. คลาส QApplication จะเป็นตัวจัดการควบคุมโปรแกรม.

บรรทัดที่ 7 สร้าง QPushButton คือปุ่มกด. Constructor ของคลาสนี้มีหลายแบบ. ในที่นี้จะตั้งค่าสายอักษรที่จะแสดงบนปุ่ม (Hello Qt!), ตัววิดเจดพ่อแม่ (parent widget) และ ชื่อวิดเจด. ตรง panrent widget เป็น 0 หมายถึงปุ่มนี้ไม่ได้อยู่ในวิดเจดอื่น. เสร็จแล้วเรียก method show() ในบรรทัดที่ 8.

ในบรรทัดที่ 9 ใช้ app จัดการตั้งวิดเจดหลักด้วยฟังก์ชัน setMainWidget( button). บรรทัดที่ 10 เป็นการเขื่อม signal กับ slot ด้วยฟังก์ชัน connect ที่กำหนดไว้ในคลาส QObject. QPushButton สืบทอดมาจาก QWidget เลยมีฟังก์ชันนี้ด้วย. ฟังก์ชัน connect มีรูปแบบเป็น

connect( sender, SIGNAL(signal ), receiver, SLOT(slot));
ในตัวอย่างเป็นการส่ง signal ชื่อ clicked() โดยปุ่ม button หาตัวเองโดยต่อกับ slot ชื่อ close(). ในความเป็นจริงแล้ว Slot ก็คือ method ของคลาสนั้น. ชื่อ signal และ slot ต้องเขียนในแมคโคร (macro) SIGNAL() และ SLOT(). moc (meta-object compiler) จะเป็นตัวจัดการแปลงเป็นไวยกรณ์ C++ มาตรฐานให้ภายหลัง.

บรรทัดที่ 11 เป็นบรรทัดสุดท้ายสั่งให้โปรแกรมวน loop. ถ้ามีการกดปุ่ม, ตัวปุ่มซึ่งเป็นวิดเจดหลักจะรับสัญญาณแล้วปิด (close) ตัวเองทำให้โปรแกรมจบการทำงาน.

ลองคอมไพล์

คราวนี้เรียกว่า Qt way เป็นวิธีที่ Qt ใช้คอมไพล์โปรแกรมตามตัวอย่างต่อไปนี้.
$ pwd 
/home/poonlap/qt/hello
$ ls 
hello.cpp
$ qmake -project
$ ls
 hello.cpp  hello.pro
$ qmake hello.pro
$ ls
Makefile  hello.cpp  hello.pro
$ make
g++ -c -pipe -Wall -W -O3 -march=pentium4 -fprefetch-loop-arrays -pipe  
-DQT_NO_DEBUG -I/usr/qt/3/mkspecs/linux-g++ -I. -I. -I/usr/qt/3/include 
-o hello.o hello.cpp
g++ -Wl,-rpath,/usr/qt/3/lib -o hello hello.o    -L/usr/qt/3/lib 
-L/usr/X11R6/lib -lqt -lXext -lX11 -lm
$ ls
Makefile  hello*  hello.cpp  hello.o  hello.pro
คำสั่ง qmake เป็นคำสั่งสำหรับสร้างไฟล์ project (.pro) สร้าง Makefile. พอได้ Makefile แล้วก็สร้างโปรแกรมได้. รันแล้วจะได้ผลเหมือนในรูป. ว่างๆกฌดูเนื้อหาไฟล์ .pro และ Makefile ที่สร้างด้วยแล้วกันว่าเป็นอย่างไร.

หลังจากที่กดปุ่มแล้วก็จะจบการทำงาน.

เริ่มต้น Qt

ต่อจากนี้ก็อ่านเอกสารของ Qt เองครับที่ doc.trolltech.com หรือใช้โปรแกรม assistant จะแสดงเบราว์เซอร์ดูคู่มือที่อยู่ในเครื่องได้.
Qt way - 3 นาทีกับการเขียนโปรแกรม GUI ง่ายๆบนลินุกซ์ - Tuesday, November 30, 2004 -

หนังสือ (คอมฯ) ที่มีอิทธิพลต่อข้าพเจ้า

ที่อยู่ใหม่ของ Poonlap's Linux blog : http://mm.co.th/poonlap

ระหว่างที่เดินมาทำงานนึกถึงหนังสือ (คอมพิวเตอร์) ต่างๆที่เคยอ่านในอดีตว่าเราก็อ่านหนังสือคอมพิวเตอร์ต่างๆมาเยอะ, ลองมาทบทวนดูว่ามีหนังสืออะไรที่เคยอ่านแล้วมีอิทธิพลกับเราบ้างในวันนี้.

ตอนเรียนอยู่มัธยมที่เมืองไทยไม่มีโอกาสใช้คอมพิวเตอร์. ถ้าใช้ก็ใช้เขียนรายงาน (เท่าที่จำได้เคยเขียนกับเพื่อนอยู่หนึ่งฉบับ). พอมาเรียนที่ญี่ปุ่นปีแรกก็เรียนแต่ภาษาญี่ปุ่นหนึ่งปีเต็ม. สมัยนั้นเป็นปี 1993 เครื่องคอมพิวเตอร์ที่โรงเรียนสอนภาษาญี่ปุ่น (東京外国語大学 日本語教育センター ชื่อยาวแต่เรียกสั้นๆว่า 日本語学校) มีเครื่อง Mac ให้ใช้ฝึกเขียนเรียนภาษาเท่านั้น. พอเข้าเรียนมหาวิทยาลัย (電器通信大学, The University of Electro-communications) ก็เป็นครั้งแรกที่สัมผัสกับคอมพิวเตอร์อย่างจริงจัง. เป็นดวงชะตาที่มหาวิทยาลัยใช้ UNIX (สมัยนั้นเป็น SunOS 4, ตอนนี้ไม่รู้ว่าใช้อะไรกันอยู่) ทำให้ได้รับอิทธิพล UNIX ไปเต็มที่ทำให้ชอบยูนิกซ์มาตั้งแต่ตอนนั้น. ปีหนึ่งยังเขียนโปรแกรมไม่เป็นเลยเรียนการใช้ยูนิกซ์พื้นฐานเท่านั้น.

พอขึ้นปีสองก็สมัครเข้าเรียน (วิชาเลือก, ผมไม่ได้จบ CS) วิชาเขียนโปรแกรมภาษาซีก็ได้รู้จักกับหนังสือ An Introduction to ANSI C on Unix แต่เป็นฉบับภาษาญี่ปุ่นซึ่งมารู้วันนี้เองว่าคนแปลเป็นอาจารย์ที่มหาวิทยาลัย. หนังสือเล่มนี้ดีมาก (bias) และใช้เป็นแบบเรียนในชั่วคอร์สนั้น. อธิบายตั้งแต่ยูนิกซ์เบื้องต้น, บรรณาธิกรณ์, cc, cpp, make, array, pointer ฯลฯ. แต่หลังจากที่เรียนคอร์สนั้นจบแล้วผมก็ยังไม่ค่อยเข้าใจ pointer เท่าไหร่ (slow starter). แต่ก็จับหูจับหางเขียน cgi เป็นภาษาซีได้ (สมัยนี้คงไม่มีใครบ้าเขียนด้วย C แน่). จากนั้นก็อ่านหนังสือเล่มนี้อีกหลายครั้งจนเข้าใจ (คิดว่า). อ่านหลายครั้งนี่คือเห็นหนังสือก็หยิบมาอ่านอีก. บางครั้งกลับไปเมืองไทยตอนปิดเทอมก็เอาไปอ่าน, ปิดเทอมครั้งถัดไปก็เอาไปอ่านอีกจนแม่ถามว่าอ่านหนังสือเล่มเดียวกันเป็นปีแล้วยังไม่จบหรือ?

นี่ก็เป็นเรื่องราวของผมกับหนังสือเล่มนี้ ครับ. แล้วจะเล่าเรื่องเล่มอื่นๆต่อครับถ้ามีโอกาส.

หนังสือ (คอมฯ) ที่มีอิทธิพลต่อข้าพเจ้า - -

Code less. Create more. - Qt

ที่อยู่ใหม่ของ Poonlap's Linux blog : http://mm.co.th/poonlap

ช่วงนี้อ่านหนังสือ C++ GUI Programming with Qt 3 อยู่เพราะมีเหตุต้องเขียนโปรแกรม C++ แบบ GUI บนลินุกซ์ (bias). ยิ่งอ่านยิ่งรู้สึกจะกลายเป็นสาวก Qt ซะแล้วเพราะรู้สึกว่าดีและสร้างโปรแกรมด้วย Qt ง่ายจริงๆ. มีแนวคิดที่ต่างจากการสร้าง GUI เรื่อง moc (meta-object complier), signal/slot (ใช้แทน callback function) ทำให้เขียนโปรแกรมได้ง่ายขึ้น.

หนังสืออ่านอยู่เป็นฉบับดาว์นโหลดแล้วเก็บไว้อ่านในรถไฟเวลาเดินทางไปทำงาน. เนื้อหาก็เหมือนกับหนังสือที่ขายแหละครับ. หลายคนอาจจะสงสัยแล้วจะขายหนังสือไปทำไม? ตอนแรกผมก็คิดอย่างนั้นเหมือนกัน. หนังสือเล่มนี้แถม CD-ROM ข้างในมี

  • Qt 3.2.1 Non-Commercial Edition for Windows
  • Qt 3.2.1 Free Edition for Mac OS X
  • Qt 3.2.1 Free Edition for Unix/Linux with X11
  • Borland C++ Builder 5 Non-Commercial Edition
  • Borland C++ Builder 6 Trial Edition
  • Source code for the book's examples
ถ้าคนใช้ที่ลินุกซ์โดยปรกติเช่นผมดาว์นโหลดหนังสือมาอ่านก็เพียงพอแล้ว. แต่ยิ่งอ่านแล้วอยากซื้อเพื่อเอา CD-ROM ครับ. สาเหตุที่สำคัญคืออยากใช้บนวินโดวส์ดูว่าเป็นอย่างไรและผมไม่มี compiler สำหรับบนวินโดวส์ด้วย. อีกอย่าง, ทาง Trolltech เองก็มีให้ดาว์นโหลด Qt สำหรับวินโดวส์เหมือนกันแต่ต้องการ Microsoft Visual C version 6 เท่านั้น (? ไม่แน่ใจ). แถมไม่ค่อยเปิดเผยเท่าไหร่ไม่เหมือนกับ Qt บนลินุกซ์. อย่างนี้ซื้อหนังสือดีกว่าได้ทั้งหนังสือและ Borland C++ Builder 5 มาใช้ด้วยกันเลย. มีคนเขียนสรุปการติดตั้ง Qt บนวินโดวส์ที่มากับหนังสือให้ดูแล้วด้วย.

ที่หนังสือแถม Borland C++ Builder นี่น่าจะเป็นเพราะ Borland ถือหุ้นของ Trolltech อยู่ด้วย 8.3 %. สรุปว่าหนังสือเล่มนี้ดีครับ. ดาว์นโหลดอ่านได้ฟรี, ใครอยากลองใช้ Qt บนวินโดวส์เช่นผมก็อาจจะซื้อหนังสือเป็นเล่มเก็บไว้, เป็นการระดมผู้พัฒนาซอฟต์แวร์แบบหนึ่ง, โฆษณา Qt, Borland ไปในตัว.

เคยเขียนโปรแกรม GUI บนลินุกซ์ด้วยด้วยภาษา C++ เลยเลือกใช้ Gtkmm (Gtk+ แบบใช้ C++) กับ glade (GUI builder)

หน้าจอ Glade

และ glademm (ตัวเปลี่ยนไฟล์ XML ของ glade ให้เป็นโค้ด Gtkmm). ใช้แล้วปรากฏว่าถ้าเปลี่ยน layout, เพิ่มลบ widget ที่สร้างใน glade แล้วมันไม่เปลี่ยนโค้ดที่สัมพันธ์ให้โดยอัตโนมัติ! เลิก. แล้วมาใช้ Qt กับ Qt designer นี่ประทับใจกว่าเยอะ.

Qt designer ใช้สร้างอินเทอร์เฟส.
Qt assistan คู่มือของ Qt

เอกสารแบบอ่านที่เครื่องก็มี assistant มีอธิบานตั้งแต่ API, tutorial ฯลฯ. หรือจะอ่านที่เว็บไซด์ของเขาก็ได้. เอกสารเป็นสิ่งสำคัญอย่างหนึ่งที่มักจะถูกละเลยซึ่งเอกสาร Qt เตรียมไว้อย่างดี.

หลังจากที่ดู Qt ก็มาเลยมาดู wxWidgets ซึ่งเป็น Toolkit สำหรับ C++ และใช้ได้ทั้งบนวินโดวส์และลินุกซ์. ได้ยินเกี่ยวกับ Toolkit ตัวนี้มานานแล้วแต่ไม่มีโอกาสได้ใช้. ดูคร่าวๆเหมือนมีอะไรคล้ายกับ signal/slot ของ Qt ด้วย. คิดว่าเป็นทางเลือกอีกทางสำหรับคนที่ต้องการเขียนโปรแกรม GUI บนลินุกซ์ด้วย C++.

สุดท้าย, เนื้อหาที่เขียนไปเป็นทัศนคติเท่านั้น, ไม่ได้ต้องการบอกว่าอะไรดีกว่าอะไร. แต่ก็มีคนถกเถียงกันพอแล้วเช่น ข้าง Qt, ข้าง Gtk.

Code less. Create more. - Qt - -

เชลล์สคริปต์เบื้องต้น ตอนที่ 4 - ตัวแปรพิเศษ

ที่อยู่ใหม่ของ Poonlap's Linux blog : http://mm.co.th/poonlap

สารบัญ

  1. เชลล์สคริปต์เบื้องต้น - สร้างและรันเชลล์สคริปต์
  2. ตัวแปร
  3. ตัวแปรสภาพแวดล้อม
  4. ตัวแปรพิเศษ
  5. ตัวแปรแถวลำดับ (array)
  6. เงื่อนไข if
  7. วงวน for
  8. วงวน while, ฟังก์ชัน
  9. ตอนจบ

วันก่อนพูดเรื่องตัวแปรสภาพแวดล้อมไปนี้วันนี้ขอพูดเรื่องตัวแปรพิเศษครับ.

ตัวแปรพิเศษ

ถ้าอ่าน man bash ในช่วงของ special parameters จะเห็นว่ามีตัวแปรพิเศษอยู่หลายตัว. ตัวแปรเหล่านี้โดยปรกติเชลล์จะเตรียมไว้ให้อยู่แล้วไม่ต้องสร้างเอง, และมักจะเป็นตัวแปรที่เปลี่ยนค่าไม่ได้ (read-only). ตัวแปรที่ใช้บ่อยและสำคัญๆได้แก่

  • $0, $1, $2, $3, ... ตัวแปรนี้เป็นตัวเลขใช้สำหรับอ้างอิงชื่อเชลล์สคริปต์และอาร์กิวเมนต์ของเชลล์สคริปต์เรียกว่า position parameter. ตัวอย่างเช่น
    #!/bin/sh
    # file: arg.sh
    echo $0 $1 $2
    
    $ ./arg.sh Hello again
    ./arg.sh Hello again
    
    $0 อ้างอิงชื่อเชลล์สคริปต์. $1 จะแทนอาร์กิวเมนต์ตัวแรกของสคริปต์, $2 แทนอาร์กิวเมนต์ตัวที่สองของสคริปต์ไปเรื่อยๆ.
  • $# ใช้บอกจำนวนอาร์กิวเมนต์.
  • $* แทนอาร์กิวเมนต์ของสคริปต์เรียงกันทั้งหมด "$1 $2 $3 ...". กรณีที่มีการตั้งแค่ตัวแปร IFS แสดงเป็น "$1$IFS$2$IFS...".
  • $@ คล้ายกับ $* แต่จะใช้ช่องว่างคั่นระหว่าง position parameter.
  • $? ตัวแปรแสดงสถานะการจบการทำงานของคำสั่งที่ผ่านล่าสุด. ถ้าคำสั่ง (โปรแกรม) จบการทำงานโดยบริบูรณ์จะมีค่าเป็น 0. ถ้าจบการทำงานโดยมี error ก็จะเป็นตัวเลขที่ไม่ใช่ 0 แล้วแต่กรณีแล้วแต่โปรแกรม. ตัวแปรนี้เอาเช็คว่าโปรแกรมที่สั่งไปทำงานถูกต้องหรือไม่. เช่น
    $ ls /etc/passwd
    $ echo $?
    0
    $ ls /etc/password
    ls: /etc/password: No such file or directory
    $ echo $?
    1
    
  • $! แสดงโปรเซส ID ของเชลล์ที่ทำงานอยู่.
ต่อไปนี้จะเป็นตัวแปรพิเศษที่อ่านแล้วเข้าใจได้ง่าย. ตัวแปรบางตัวอาจตัวค่าใหม่ได้.
  • $HOSTNAME ชื่อเครื่องที่ใช้งาน.
  • $PWD ไดเรกทอรีที่ทำงานอยู่.
  • $OLDPWD ไดเรกทอรีก่อนหน้าไดเรกทอรีปัจจุบัน.
  • $RANDOM ตัวเลขสุ่มระหว่าง 0 และ 32767.
  • $HOME โฮมไดเรกทอรี.
  • $PS1 ตัวแปรเก็บค่าพรอมต์หลัก (primary prompt)
  • $PS2 ตัวแปรเก็บค่าพรอมต์รอง (secondary prompt). ค่าโดยปริยายจะเป็น ">"
    $ for animal in Dog Cat Rat
    > do
    > echo $animal
    > done
    Dog
    Cat
    Rat
    
    ตามธรรมเนียมของ bash แล้วเชลล์พรอมต์ของยูสเซอร์ทั่วไปมักจะแทนด้วย "$" และสำหรับ root จะแทนด้วย "#".

การอ้างอิงตัวแปร

เรารู้แล้วว่าการอ้างอิงตัวแปรให้ใช้เครื่องหมาย "$" นำหน้าตัวแปรก็จะได้ค่าตัวแปร. มีบางกรณีที่เราต้องการอ้างอิงตัวแปรแล้วเขียนคำถัดจากตัวแปรเลยเช่น

$ a=temporary
$ echo $a.txt
temporary.txt

ในกรณีนี้จะไม่มีปัญหาอะไรเพราะเชลล์ตีความตัวแปรถึงแค่เครื่องหมาย "." คือเชลล์จะแทนค่า "$a" ด้วย "temporary" แล้วแสดงคำว่า ".txt" ตามทันที. แต่คำที่ต่อจากตัวแปรไม่ใช่จุดเช่น "_file", เชลล์จะตีความเป็นการอ้างอิงถึงตัวแปรชื่อ "a_file" ซึ่งไม่มีตัวตน (ว่างเปล่า). เพื่อความชัดเจนในกรณีนี้ให้ใช้เครื่องหมายวงเล็บปีกกาช่วยระบุช่วงของตัวแปรที่ต้องการแสดงตัวอย่างเช่น.

$ echo ${a}_file
temporary_file

หมายเหตุ

เครื่องหมาย "#" ใช้แสดงหมายเหตุ, เขียนไว้ตรงไหนในเชลล์สคริปต์ก็ได้ (ยกเว้นบรรทัดแรก). เชลล์จะถือว่าข้อความที่เขียนหลังเครื่องหมาย "#" จนสิ้นสุดบรรทัดเป็นหมายเหตุ (comment). เอาไว้ใช้เขียนบรรทึกในสคริปต์อธิบายสิ่งที่เขียน.

#!/bin/sh
#
# Filename: comment.sh
# This is a test script
#
echo Hello world! # This is a comment. Shell will ignore this.
$ ./comment.sh
Hello world!
เชลล์สคริปต์เบื้องต้น ตอนที่ 4 - ตัวแปรพิเศษ - Monday, November 29, 2004 -

ลองใช้ Gmail ด้วย POP โปรโตคอล

ที่อยู่ใหม่ของ Poonlap's Linux blog : http://mm.co.th/poonlap

วันนี้เพิ่งได้ลองดาว์นโหลดเมลล์ด้วย POP โปรโตคอลจาก Gmail วันนี้หลังจากที่เคยอ่านบน Slashdot ว่า Gmail อนุญาตให้ใช้ POP แล้ว. ใช้ได้ดีทีเดียว. เวลา authenticate จะใช้ SSL ( Secured Sockets Layer) และมี SMTP (Simple Mail Transfer Protocol) เซิฟร์เวอร์ให้ใช้ด้วย. คนที่มี Gmail account ก็สามารถเก็บเมลล์ไว้ที่เซิฟร์เวอร์ด้วยก็ได้.

ตอนที่ใช้ Gmail จากเว็บได้อย่างเดียวมีปัญหาเรื่องภาษาไทยจะเป็น UTF-8 หมดทำให้ webmail บางตัวอ่านไม่ออก. แต่ตอนนี้ใช้ mail client ส่งทาง SMTP คิดว่าน่าจะแก้ปัญหานี้ได้ครับ.

ลองใช้ Gmail ด้วย POP โปรโตคอล - Friday, November 26, 2004 -

เชลล์สคริปต์เบื้องต้น ตอนที่ 3 - ตัวแปรสภาพแวดล้อม

ที่อยู่ใหม่ของ Poonlap's Linux blog : http://mm.co.th/poonlap

สารบัญ

  1. เชลล์สคริปต์เบื้องต้น - สร้างและรันเชลล์สคริปต์
  2. ตัวแปร
  3. ตัวแปรสภาพแวดล้อม
  4. ตัวแปรพิเศษ
  5. ตัวแปรแถวลำดับ (array)
  6. เงื่อนไข if
  7. วงวน for
  8. วงวน while, ฟังก์ชัน
  9. ตอนจบ

ตัวแปรสภาพแวดล้อม

ตัวแปรที่ใช้ในเชลล์จะมีสองแบบคือตัวแปรธรรมดากับตัวแปรสภาพแวดล้อม (environment variable). ตัวแปรสภาพแวดล้อมจริงๆแล้วก็คือตัวแปรธรรมดาแต่มีผลที่โปรแกรมที่รันในเชลล์นั้นจะสืบทอดตัวแปรสภาพแวดล้อมและค่านั้นไปด้วย. ตัวอย่างตัวแปรสภาพแวดล้อมที่เราคุ้นเคยกันเช่น PATH เป็นต้น.

การสร้างตัวแปรสภาพแวดล้อมเหมือนกับการสร้างตัวแปรทั่วไป. แต่หลังจากที่สร้างตัวแปรทั่วไปแล้วต้องประกาศตัวแปรนั้นให้เป็นตัวแปรสภาพแวดล้อมด้วยคำสั่ง export.

$ MY_ENV_VAR="example of environment variable"
$ export MY_ENV_VAR

หรือจะตั้งแค่ตัวแปรและประกาศตัวแปรสภาพแวดล้อมพร้อมๆกันก็ได้.

$ export MY_ENV_VAR="example of environment variable"

ตัวแปรสภาพแวดล้อมมักจำใช้ชื่อตัวแปรเป็นตัวอักษรตัวใหญ่แต่ไม่จำเป็น. เราลองมาดูผลกระทบของตัวแปรสภาพแวดล้อมต่อโปรแกรมที่รันในเชลล์นั้นๆดู.

สมมติว่าเรามีเชลล์สคริปต์ที่แสดงค่าตัวแปรตามตัวอย่างต่อไปนี้.
#!/bin/sh
# file: env.sh
echo $MY_ENV_VAR
echo $MY_VAR

เชลล์สคริปต์นี้ไม่ได้ทำอะไรพิสดาร, แค่แสดงค่าของตัวแปร MY_ENV_VAR กับ MY_VAR เท่านั้น. ที่นี้เราลองรันในเชลล์ที่มีตัวแปรสภาพแวดล้อม MY_ENV_VAR และตัวแปรธรรมดา MY_VAR ดูว่าจะได้ผลอย่างไรดู.

$ export MY_ENV_VAR="example of environment variable"
$ MY_VAR="Normal variable"
$ ./env.sh
example of environment variable
 
$ . env.sh
example of environment variable
Normal variable

ผลของการรันเชลล์สคริปต์จะไม่เหมือนกัน. ทำไม? การรันเชลล์สคริปต์แบบแรกเชลล์ที่รันอยู่จะเรียกเชลล์ตัวใหม่ (สร้างโปรเซสใหม่) และเชลล์ตัวใหม่จะเป็นตัวกระทำการ. เชลล์ตัวใหม่ในที่นี้คือบรรทัด #!/bin/sh นั่นเอง. เชลล์ (โปรแกรม) ที่เกิดใหม่สืบทอดตัวแปรสภาพแวดล้อม MY_ENV_VAR มาด้วยทำให้แสดงผลได้. แต่ไม่สามารถแสดงค่าของตัวแปร MY_VAR ได้เพราะไม่ใช้ตัวแปรสภาพแวดล้อม (ไม่สืบทอดไปสู่โปรแกรมอื่น).

ส่วนการรันเชลล์สคริปต์แบบที่สองโดยใช้ "." (dot). เป็นการใช้เชลล์ที่ทำงานอยู่ในปัจจุบันอ่านไฟล์ env.sh ไม่ได้เป็นการสร้างเชลล์ใหม่. ดังนั้นจึงสามารถแสดงค่าของตัวแปรทั้งสองตัวได้. คำสั่งที่เทียบเท่ากับ "." คือ source ใช้สำหรับอ่านข้อมูลเข้าไปในเชลล์ที่ใช้อยู่. ตัวอย่างเช่นในไฟล์ ~/.bashrc มักจะตั้งค่าตัวแปรต่างๆไว้. ไฟล์นี้จะถูกอ่าน (ถูกกระทำการ) ตอนที่เชลล์เริ่มทำงาน. ถ้ามีการแก้ไขไฟล์นี้แล้วอยากให้มีผลทันทีโดยไม่ต้องเริ่มเชลล์ใหม่ก็เพิ่งแค่ source ~/.bashrc เรียกอ่านเนื้อหาในไฟล์นั้นโดยใช้เชลล์ที่ทำงานอยู่ในปัจจุบัน.

ดูค่าตัวแปรสภาพแวดล้อม

เราจะรู้ได้อย่างไรว่ามีตัวแปรสภาพแวดล้อมอะไรบ้างในขณะนี้? คำสั่งที่ใช้บอกตัวแปรสภาพแวดล้อมก็คือคำสั่งเดียวกันกับที่ใช้ประกาศตัวแปรสภาพแวดล้อมซึ่งก็คือ export.

$ export
declare -x CC="gcc"
declare -x CLASSPATH="/opt/blackdown-jdk-1.4.1/jre/lib/rt.jar:."
declare -x COLORTERM="gnome-terminal"
declare -x CONFIG_PROTECT="/var/bind /usr/lib/mozilla/defaults/pref 
/usr/X11R6/lib/X11/xkb /usr/kde/3.2/share/config /usr/kde/3.1/share/config 
/usr/share/texmf/tex/generic/config/ /usr/share/texmf/tex/platex/config/ 
/usr/share/texmf/dvips/config/ /usr/share/texmf/dvipdfm/config/ 
/usr/share/texmf/xdvi/ /usr/share/config"
declare -x CONFIG_PROTECT_MASK="/etc/gconf /etc/terminfo"
declare -x CVSROOT=":pserver:poonlap@linux.thai.net:/home/cvs"
declare -x CVS_RSH="ssh"
declare -x CXX="g++"
declare -x DESKTOP_SESSION="gnome"
declare -x DISPLAY=":0.0"
declare -x EDITOR="/usr/bin/vim"
declare -x GDK_USE_XFT="1"
declare -x GDMSESSION="gnome"
declare -x GLIBC_SSP_CHECKED="1"
declare -x GNOME_DESKTOP_SESSION_ID="Default"
declare -x GNOME_KEYRING_SOCKET="/tmp/keyring-N1Rd2c/socket"
declare -x GTK_RC_FILES="/etc/gtk/gtkrc:/home/poonlap/.gtkrc-1.2-gnome2"
declare -x GUILE_LOAD_PATH="/usr/share/guile/1.6"
declare -x G_BROKEN_FILENAMES="1"
declare -x HOME="/home/poonlap"
declare -x HOSTNAME="justice"
declare -x INFODIR="/usr/share/info"
declare -x INFOPATH="/usr/share/info:/usr/share/gcc-data/i686-pc-linux-gnu/3.3
/info"
declare -x INPUTRC="/etc/inputrc"
declare -x JAVAC="/opt/blackdown-jdk-1.4.1/bin/javac"
declare -x JAVA_HOME="/opt/blackdown-jdk-1.4.1"
declare -x JDK_HOME="/opt/blackdown-jdk-1.4.1"
declare -x KDEDIR="/usr/kde/3.2"
declare -x KDEDIRS="/usr"
declare -x LESS="-R"
declare -x LESSOPEN="|lesspipe.sh %s"
declare -x LOGNAME="poonlap"
declare -x LS_COLORS="no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01
:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=01;32:*.cmd=01;32:*.exe=01;32:*.
com=01;32:*.btm=01;32:*.bat=01;32:*.sh=01;32:*.csh=01;32:*.tar=01;31:*.tgz=01;
31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;
31:*.bz2=01;31:*.bz=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.rar=01;31:*.ace=
01;31:*.zoo=01;31:*.cpio=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35
:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png
=01;35:*.mng=01;35:*.xcf=01;35:*.pcx=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35
:*.avi=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.mov
=01;35:*.qt=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*
.fli=01;35:*.gl=01;35:*.dl=01;35:"
declare -x MANPATH="/usr/share/man:/usr/local/share/man:/usr/share/gcc-data/i686-pc-linux-
gnu/3.3/man:/usr/share/man:/opt/blackdown-jdk-1.4.1/man:/usr/qt/3/doc/man:/opt/
vmware/man"
declare -x MOZILLA_FIVE_HOME="/usr/lib/mozilla"
declare -x MY_ENV_VAR="example of environment variable"
declare -x OLDPWD="/home/poonlap"
declare -x PAGER="/usr/bin/less"
declare -x PATH="/bin:/usr/bin:/usr/local/bin:/opt/bin:/usr/i686-pc-linux-gnu/gcc-bin/3.3:
/opt/Acrobat5:/usr/X11R6/bin:/opt/blackdown-jdk-1.4.1/bin:/opt/blackdown-jdk-1.
4.1/jre/bin:/usr/qt/3/bin:/usr/kde/3.2/bin:/usr/kde/3.1/bin:/opt/firebird/bin:
/opt/vmware/bin"
declare -x PS1="\\[\\033[01;32m\\]\\u@\\h \\[\\033[01;34m\\]\\W \\\$ \\[\\033[0
0m\\]"
declare -x PWD="/home/poonlap/tmp"
declare -x QMAKESPEC="linux-g++"
declare -x QTDIR="/usr/qt/3"
declare -x SESSION_MANAGER="local/justice:/tmp/.ICE-unix/7010"
declare -x SHELL="/bin/bash"
declare -x SHLVL="1"
declare -x SSH_AGENT_PID="7031"
declare -x SSH_AUTH_SOCK="/tmp/ssh-mqxqiU7010/agent.7010"
declare -x TERM="xterm"
declare -x USER="poonlap"
declare -x USERNAME="poonlap"
declare -x WINDOWID="21507072"
declare -x XAUTHORITY="/home/poonlap/.Xauthority"
declare -x XINITRC="/etc/X11/xinit/xinitrc"
declare -x XPSERVERLIST=""

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

ถ้าต้องการเปลี่ยนตัวแปรสภาพแวดล้อมเป็นตัวแปรธรรมดาก็ใช้ตัวเลือก -n ร่วมกับคำสั่ง export เช่น.

$ export -n MY_ENV_VAR
เชลล์สคริปต์เบื้องต้น ตอนที่ 3 - ตัวแปรสภาพแวดล้อม - Thursday, November 25, 2004 -

เชลล์สคริปต์เบื้องต้น ตอนที่ 2

ที่อยู่ใหม่ของ Poonlap's Linux blog : http://mm.co.th/poonlap

สารบัญ

  1. เชลล์สคริปต์เบื้องต้น - สร้างและรันเชลล์สคริปต์
  2. ตัวแปร
  3. ตัวแปรสภาพแวดล้อม
  4. ตัวแปรพิเศษ
  5. ตัวแปรแถวลำดับ (array)
  6. เงื่อนไข if
  7. วงวน for
  8. วงวน while, ฟังก์ชัน
  9. ตอนจบ

ต่อจากตอนที่ 1.

รันเชลล์สคริปต์

วิธีการรันเชลล์สคริปต์เหมือนเป็นเรื่องที่ไม่ต้องสอนกันแต่คนเริ่มต้นใหม่ๆอาจจะตกหลุมได้ง่ายๆ. ถ้าคุณมีเชลล์สคริปต์อยู่ในไดเรกทอรีที่ทำงานอยู่แล้วรันเชลล์สคริปต์เหมือนกับคำสั่งทั่วๆไปอาจจะเกิดข้อผิดพลาดได้.

$ hello.sh
-bash: hello.sh: command not found
$ ./hello.sh
Hello world!

อันนี้เป็นเพราะไดเรกทอรีปัจจุบันซึ่งได้แก้เครื่องหมาย "." ไม่ได้อยู่ในตัวแปรสภาพแวดล้อม (environment variable) PATH.

$ echo $PATH
/bin:/usr/bin:/usr/local/bin:/opt/bin:/usr/i686-pc-linux-gnu/gcc-bin/3.3:/opt/Acro
bat5:/usr/X11R6/bin:/opt/blackdown-jdk-1.4.1/bin:/opt/blackdown-jdk-1.4.1/jre/bin:
/usr/qt/3/bin:/usr/kde/3.2/bin:/usr/kde/3.1/bin:/opt/vmware/bin:/home/poonlap/bin

ตัวแปรสภาพแวดล้อม PATH เป็นตัวแปรที่เก็บไดเรกทอรีต่างๆขั้นด้วยเครื่องหมาย : บอกให้เชลล์รู้ว่าโปรแกรมที่ใช้ได้อยู่ในระบบอยู่ในไดเรกทอรีเหล่านี้. กล่าวคือเชลล์จะใช้ตัวแปรสภาพแวดล้อม PATH ในการหาว่าคำสั่ง (โปรแกรม) อยู่ที่ไหน. ดังนั้นถ้ารันเชลล์สคริปต์โดยไม่ใส่เครื่องหมาย "./" จะหมายความว่า "hello.sh" เป็นโปรแกรมคำสั่งที่อยู่ในไดเรกทอรีที่กำหนดไว้ในตัวแปรสภาพแวดล้อม PATH ซึ่งจริงๆแล้ว "." (ไดเรกทอรีปัจจุบัน) ไม่ได้อยู่ใน PATH จึงต้องอ้างอิงสคริปต์โดยใช้ relative path คือ "./" บอกกับเชลล์ว่า hello.sh อยู่ที่นี่ (ไดเรกทอรีที่ทำงานอยู่).

อีกวิธีหนึ่งสำหรับการรันเชลล์สคริปต์ซึ่งไม่ค่อยทำกันได้แก่

$ sh hello.sh
Hello world!
$ . hello.sh
Hello world!

อันนี้จะเป็นการเรียกใช้โปรแกรม sh ซึ่งก็คือ bash แปลคำสั่งที่อยู่ในไฟล์ hello.sh ก็คือการรันสคริปต์นั่นเอง. ส่วนแบบที่สองคือการใช้คำสั่ง "." อ่านเนื้อหาในไฟล์ hello.sh แล้วตีความ.

ตัวแปร

เชลล์สคริปต์เหมือนกับโปรแกรมทั่วไปที่มีตัวแปรไว้เก็บค่าต่างๆ. ตัวแปรที่ใช้ในเชลล์ไม่ต้องประกาศประเภทตัวแปรเหมือนภาษาซีและสามารถตั้งค่าใช้ได้ทันที. การตั้งค่าตัวแปรจะมีรูปแบบเป็น.

ชื่อตัวแปร=ค่าตัวแปร

ข้อควรระวังคือช่วงก่อนหน้าและหลังเครื่องหมายเท่ากับห้ามมีช่องว่าง เพราะเชลล์ถือว่าช่องว่าคือตัวแบ่งอาร์กิวเมนต์. ตัวอย่างการสร้างตัวแปรเช่น

var1=Hello
var2=world!

เวลาต้องการแสดงค่าให้ใช้เครื่องหมายดอลล่าร์นำหน้าตัวแปร.

echo $var1 $var2

Quote และ Double quote

ช่องว่าง (space) มีความหมายพิเศษสำหรับเชลล์ไว้สำหรับแบ่งอาร์กิวเมนต์. ดังนั้นถ้าต้องการตั้งค่าตัวแปรที่มีช่องว่าอยู่เช่น "Hello world!" ตัวใช้เครื่องหมายคำพูด quote (') หรือ double quote (") คล่อมคำที่ต้องการ.

var3='Hello world!'
var4="Hello world!" 

ความแตกต่างระหว่าง quote และ double quote คือสิ่งที่พิมพ์ใน quote จะมีค่าตามสิ่งที่พิมพ์. ในเครื่องหมาย double quote สามารถอ้างอิงค่าตัวแปรหรือนำผลลัพธ์ของคำสั่งอื่นมาใส่ได้.

var5='$var1 $var2'
var6="$var1 $var2"

ตัวอย่างเชลล์สคริปต์ต่อไปนี้สาธิตการสร้างตัวแปรและแสดงความแตกต่างระหว่าง quote กับ double qoute.

#!/bin/sh
var1=Hello
var2=world!
var3='Hello world!'
var4="Hello world!" 
var5='$var1 $var2'
var6="$var1 $var2"
echo $var1 $var2
echo $var3
echo $var4
echo $var5
echo $var6

รันได้ผลเป็นแบบนี้.

$ ./var.sh
Hello world!
Hello world!
Hello world!
$var1 $var2
Hello world!
เชลล์สคริปต์เบื้องต้น ตอนที่ 2 - Wednesday, November 24, 2004 -

เชลล์สคริปต์เบื้องต้น ตอนที่ 1

ที่อยู่ใหม่ของ Poonlap's Linux blog : http://mm.co.th/poonlap

สารบัญ

  1. เชลล์สคริปต์เบื้องต้น - สร้างและรันเชลล์สคริปต์
  2. ตัวแปร
  3. ตัวแปรสภาพแวดล้อม
  4. ตัวแปรพิเศษ
  5. ตัวแปรแถวลำดับ (array)
  6. เงื่อนไข if
  7. วงวน for
  8. วงวน while, ฟังก์ชัน
  9. ตอนจบ

ขอเริ่มเรื่องสั้นๆแนะนำเชลล์สคริปต์เบื้องต้นไปแต่ละวันแล้วกันครับจะได้ไม่หมดมุขมีอะไรเขียนใน blog บ้าง. อาจจะเป็นประโยชน์สำหรับผู้ที่เริ่มใช้ลินุกซ์และอยากเรียนรู้ลึกไปอีกหน่อยนอกเหนือจากการใช้ desktop environment ทั่วๆไปครับ.

เชลล์คืออะไร

ตอบง่ายๆ, เชลล์ (shell) คือโปรแกรมแปลคำสั่งที่พิมพ์จากคีย์บอร์ดแล้วตีความคำสั่งที่พิมพ์เพื่อทำงานต่อไป. ที่เรียกว่าเชลล์เพราะเชลล์เป็นเหมือนเปลือกหุ้มเคอร์เนลไว้, เป็นตัวกลาง (interface) ระหว่างผู้ใช้กับเคอร์เนล. การสั่งงานเช่นการเรียกใช้โปรเแกรมจากผู้ใช้ทุกอย่างต้องผ่านทางเชลล์. แต่ในสมัยนี้การสั่งงานทำผ่าน GUI (Graphical User Interface) ก็ได้.

ประเภทของเชลล์

โปรแกรมเชลล์ในโลกนี้มีหลายตัว. โปรแกรมเชลล์เริ่มแรกสมัยที่สร้างยูนิกซ์ใหม่ๆได้แก่ Bourn shell (รู้จักกันในชื่อ sh) มีชื่อตามผู้สร้างได้แก่นาย Steve Bourne. ต่อจากนั้นในสมัยของ BSD ยูนิกซ์นาย Bill Joy ก็สร้างเชลล์ตัวใหม่ที่มีคุณสมบัติเพิ่มเติมต่างๆเช่น ประวัติคำสั่ง (history), การควบคุมจ็อบ (job control) ฯลฯ. เชลล์ตัวใหม่ที่ Bill Joy สร้างนี้มีไวย์กรณ์การใช้งานคล้ายเหมือนภาษาซี (C language) และมีชื่อว่า C shell (csh). ในภายหลังก็มีเชลล์อื่นๆอีกมากมายเช่น Korn shell (ksh) มีไวย์กรณ์เหมือนกับ sh แต่มีความสามารถที่ csh ทำได้. ส่วนเชลล์ปริยายที่ลินุกซ์ใช้คือ GNU Bourne-Again Shell หรือเป็นที่รู้จักกันในนามของ bash สร้างโดย Free Software Foundation. นอกจากนี้ยังมีเชลล์สุดขั้วของเชลล์คือ zsh. "z" ในที่นี้หมายถึงตัวอักษรตัวสุดท้ายคือสื่อความหมายว่าอยากให้เป็นเชลล์ตัวสุดท้ายและเป็นเชลล์ที่ดีที่สุด. ผมไม่เคยใช้ zsh แต่ดูๆแล้วทำอะไรต่อมิอะไรได้ที่เชลล์อื่นๆไม่ทำ.

Hello world!

เชลล์สคริปต์เป็นไฟล์เท็กซ์ธรรมดาจะสร้างด้วยบรรณาธิกรณ์ (editor) อะไรก็ได้ที่ชอบเช่น vi, emacs, nano, gedit ฯลฯ. ต่อไปนี้เป็นตัวอย่างเชลล์สคริปต์ที่แสดงคำว่า "Hello world!" บนหน้าจอครับ.

#!/bin/sh
echo "Hello world!"

สมมติว่าไฟล์นี้มีชื่อว่า hello.sh ก่อนที่จะรันสคริปต์ได้ต้องทำให้ไฟล์นี้สามารถกระทำการได้ก่อนด้วยคำสั่ง chmod.

$ ls -l hello.sh
-rw-r--r--    1 poonlap  users          30 Nov 24 23:17 hello.sh
$ chmod +x hello.sh
$ ls -l hello.sh
-rwxr-xr-x    1 poonlap  users          30 Nov 24 23:17 hello.sh

ถ้าดูไฟล์ด้วยคำสั่ง ls จะเห็นว่าสิทธิ์การใช้ไฟล์เปลี่ยนเป็น -rwxr-xr-x. "x" หมายความว่ากระทำการได้ (executable).

เสร็จแล้วลองรันเชลล์สคริปต์ดู.

$ ./hello.sh
Hello world!

เชลล์สคริปต์นี้ไม่ได้ทำอะไรพิเศษเพียงแต่ใช้คำสั่ง echo แสดงคำว่า "Hello world!" ออกทางหน้าจอเท่านั้น. บรรทัดแรกของเชลล์สคริปต์ทุกตัวต้องขึ้นต้นด้วย.

#!/bin/sh

"#!" เรียกว่า sha-bang เป็นสัญลักษณ์บอกว่าไฟล์นี้เป็นสคริปต์และใช้ /bin/sh เป็นตัวแปรภาษา (interpreter). ให้สังเกตว่าตัวแปรภาษาคือ /bin/sh ไม่ใช่ bash. อันนี้เพื่อความเข้ากันได้กับเชลล์สคริปต์เก่าๆเช่น Bourne shell จึงใช้ /bin/sh. จริงๆแล้ว /bin/sh เป็น symbolic link ไปหา /bin/bash.

เชลล์สคริปต์เบื้องต้น ตอนที่ 1 - -

คำสั่ง top

ที่อยู่ใหม่ของ Poonlap's Linux blog : http://mm.co.th/poonlap

ถ้าพูดถึงคำสั่ง top เรามักจะนึกถึงการแสดงเปอร์เซ็นต์การใช้งานของหน่วยประมวล. แต่จริงๆมันแสดงรายละเอียดต่างๆของโปรเซสได้ดีจริงๆไม่แพ้คำสั่ง ps.

รูปตัวอย่างเป็นการแสดงหน้าต่าง 4 อย่างได้แก่ Def, Job, Mem และ Usr ในหน้าจอเดียว (กด "A") และใช้สี (กด "z"). ถ้าอยากเก็บการแสดงผลแบบนี้ในครั้งต่อไปก็กด "W" แล้วโปรแกรมจะเขียนไฟล์ตั้งค่าเริ่มต้นไว้ที่ ~/.toprc ครับ.

ถ้าดูในไฟล์ตั้งค่าเริ่มต้นที่เก็บค่าที่ติดตั้งไว้แล้วจะเห็นเป็นแบบนี้ครับ.

$ cat ~/.toprc
RCfile for "top with windows"           # shameless braggin'
Id:a, Mode_altscr=1, Mode_irixps=1, Delay_time=3.000, Curwin=0
Def     fieldscur=AEHIOQTWKNMbcdfgjplrsuvyzX
        winflags=64825, sortindx=10, maxtasks=0
        summclr=1, msgsclr=1, headclr=3, taskclr=1
Job     fieldscur=ABcefgjlrstuvyzMKNHIWOPQDX
        winflags=64825, sortindx=0, maxtasks=0
        summclr=6, msgsclr=6, headclr=7, taskclr=6
Mem     fieldscur=ANOPQRSTUVbcdefgjlmyzWHIKX
        winflags=64825, sortindx=13, maxtasks=0
        summclr=5, msgsclr=5, headclr=4, taskclr=5
Usr     fieldscur=ABDECGfhijlopqrstuvyzMKNWX
        winflags=64825, sortindx=4, maxtasks=0
        summclr=3, msgsclr=3, headclr=2, taskclr=3

คำสั่ง top - Monday, November 22, 2004 -

Firefox ICU patch ใน Gentoo

ที่อยู่ใหม่ของ Poonlap's Linux blog : http://mm.co.th/poonlap

คุณโชครายงานมาว่าออก Firefox 1.0 ที่ลง patch ICU ไว้ตัดคำภาษาไทยในลินุกซ์ทะเลรุ่นใหม่แล้วเลยอยากมาลองกับ Firefox ใน Gentoo บ้าง. ทำแบบนี้ครับ.
  1. ดึงข้อมูลแพกเกจล่าสุดมาก่อน.
    # emerge sync
    
  2. ดาว์นโหลด patch ไปไว้ที่ได้เรกทอรี files. รู้สึกว่ามันเป็น patch สำหรับ 0.9.2 แต่ก็น่าจะใช้ได้, ต้องลองดู.
    # cd  /usr/portage/net-www/mozilla-firefox/files
    # wget -nd ftp://ftp.opentle.org/people/mrchoke/patches/firefox-0.9.2-icu-thai-lwbr.patch
    
  3. emerge icu ก่อนถ้ายังไม่มีในระบบ.
    # emerge icu
    
  4. ตรวจสอบดูว่า firefox รุ่นล่าสุดคืออันไหน.
    # emerge -pv mozilla-firefox
     
    These are the packages that I would merge, in order:
     
    Calculating dependencies ...done!
    [ebuild     U ] net-www/mozilla-firefox-1.0-r3 [1.0-r2] -debug +gnome +java +ldap 
    -mozdevelop -moznoxft -mozsvg -mozxmlterm -xinerama -xprint 0 kB
     
    Total size of downloads: 0 kB
     
    
  5. ในกรณีนี้คือ 1.0-r3 เพราะฉะนั้นไปแก้ไฟล์ mozilla-firefox-1.0-r3.ebuild ที่อยู่ในไดเรกทอรี /usr/portage/net-www/mozilla-firefox. เพิ่มบรรทัด
            epatch ${FILESDIR}/firefox-0.9.2-icu-thai-lwbr.patch
    
    ต่อจากบรรทัด
            epatch ${FILESDIR}/mozilla-firefox-1.0-kp_separator.patch
    
    
  6. ตรงบรรทัด
     mozconfig_annotate '' --enable-oji --enable-mathml
    
    แก้เป็น
     mozconfig_annotate '' --enable-ctl --enable-oji --enable-mathml
    
    คือเพิ่มความสามารถ complex text layout ไปด้วย. จะแสดงสระไม่ลอย.
  7. emerge
    # USER="xprint" emerge mozilla-firefox
    Calculating dependencies ...done!
    >>> emerge (1 of 1) net-www/mozilla-firefox-1.0-r3 to /
    >>> md5 src_uri ;-) firefox-1.0-source.tar.bz2
    >>> Unpacking source...
    >>> Unpacking firefox-1.0-source.tar.bz2 to /var/tmp/portage/mozilla-firefox-1.0-r3/work
     * Applying mozilla-firefox-1.0-4ft2.patch ...                            [ ok ] 
     * Applying mozilla-firefox-1.0-kp_separator.patch ...                    [ ok ] 
     * Applying firefox-0.9.2-icu-thai-lwbr.patch ...                         [ ok ]
    >>> Source unpacked.
    ~x86
    ...
        --enable-ctl                    mozilla.org default
    ...
    
    ดูตอนคอมไพล์ว่าต้องเป็นอย่างตัวอย่างข้างบนครับคือมีการ patch และ --enable-ctl.
  8. ขั้นสุดท้ายเกี่ยวกับ ctl ต้องไปแก้ไฟล์ /usr/lib/MozillaFirefox/res/fonts/fontEncoding.properties. เพิ่มบรรทัดต่อไปนี้
    encoding.loma.ttf = x-thaittf-0.wide
    encoding.kinnari.ttf = x-thaittf-0.wide
    encoding.tlwgtypewriter.ttf = x-thaittf-0.wide
    encoding.tlwgmono.ttf = x-thaittf-0.wide
    encoding.purisa.ttf = x-thaittf-0.wide
    
    ถัดจากบรรทัด
    encoding.norasi.ttf = x-thaittf-0.wide
    encoding.garuda.ttf = x-thaittf-0.wide
    encoding.dbthaitext.ttf = x-thaittf-0.wide
    
    ตรงนี้จะแก้ที่รหัสต้นฉบับก่อนคอมไพล์ก็ได้แต่ลืมครับ.

หน้าจอจะเป็นแบบนี้ครับ.

ขยายจอออกอีกนิดจะเห็นว่าตัดคำได้สวย, และสระวรรณยุกต์ไม่ลอย. ต้องขอขอบคุณคนทำ patch จริงๆNATTAPOL KRITSUTHIKUL สำหรับ patch อันนี้และคุณสัมพันธ์สำหรับ patch อันใหม่.

อันนี้เป็น patch เก่า, ใช้ได้ดีแต่ช้าไปหนึ่งวินาทีถ้ามีการย่น/ขยายหน้าจอ. เห็นคุณโชคบอกว่า patch อันใหม่เร็วขึ้นแต่ผมลองแล้วไม่เห็นตัดคำให้เลย. แล้วจะลองใหม่ครับ.

Firefox ICU patch ใน Gentoo - Friday, November 19, 2004 -

NPTL

ที่อยู่ใหม่ของ Poonlap's Linux blog : http://mm.co.th/poonlap

วันนี้อยากใช้ Native POSIX Thread Library for Linux หลังจากที่ทนไม่ได้เวลา ps หรือ top แล้วมันแสดง thread เป็นโปรเซสหลายๆตัวสำหรับโปรแกรมที่ใช้ POSIX thread (pthread) เช่น firefox, nautilus. ก็เลยจัดการคอมไพล์ glibc ใหม่ใน Gentoo ที่ใช้อยู่.
# emerge -pv glibc
                                                                                
These are the packages that I would merge, in order:
                                                                                
Calculating dependencies ...done!
[blocks B     ] sys-kernel/linux-headers (from pkg sys-kernel/linux26-headers-2.6.8.1-r1)
[ebuild  N    ] sys-kernel/linux26-headers-2.6.8.1-r1  -build 34,793 kB
[ebuild     U ] sys-libs/glibc-2.3.4.20041102 [2.3.2-r9] -build -debug -erandom
 -hardened -multilib +nls -nomalloccheck +nptl* -nptlonly -pic 
-userlocales 17,112 kB
                                                                                
Total size of downloads: 51,905 kB
emerge รายงานว่าทำไม่ได้เพราะ confilct กับ sys-kernel/linux-headers. ต้องเอาแพกเกจนั้นออกก่อน.
# emerge -C linux-headers
...
# emerge -pv glibc
 
These are the packages that I would merge, in order:
 
Calculating dependencies ...done!
[blocks B     ] sys-kernel/linux-headers (from pkg sys-kernel/linux26-headers-2.6.8.1-r1)
[ebuild  N    ] sys-kernel/linux-headers-2.4.22  -build 28,836 kB
[ebuild  N    ] sys-kernel/linux26-headers-2.6.8.1-r1  -build 34,793 kB
[ebuild     U ] sys-libs/glibc-2.3.4.20041102 [2.3.2-r9] -build -debug -erandom
 -hardened -multilib +nls -nomalloccheck +nptl* -nptlonly -pic 
-userlocales 17,112 kB
 
Total size of downloads: 80,742 kB
มันยังขึ้นเหมือนเดิมแต่ไม่เป็นไร, ใส่ linux26-headers ให้ไปก่อนแล้วค่อยว่ากันใหม่.
# emerge  linux26-headers
แล้วดูอีกทีครับ.
# emerge -pv glibc
 
These are the packages that I would merge, in order:
 
Calculating dependencies ...done!
[ebuild     U ] sys-libs/glibc-2.3.4.20041102 [2.3.2-r9] -build -debug -erandom
 -hardened -multilib +nls -nomalloccheck +nptl* -nptlonly -pic 
-userlocales 17,112 kB
 
Total size of downloads: 17,112 kB
 
ปรากฏว่า emerge ยอมแล้วก็ลุยเลย.
# emerge glibc
อันนี้จะกินเวลาคอมไพล์นานมากๆ. เสร็จแล้วรัน etc-update เป็นอันว่าเรียบร้อยครับ. ตรวจสอบดูโดยรัน /lib/libc.so.6
$ /lib/libc.so.6
GNU C Library 20041102 release version 2.3.4, by Roland McGrath et al.
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 3.3.3 20040412 (Gentoo Linux 3.3.3-r3, ssp-3.3-7, pie-8.5.3).
Compiled on a Linux 2.6.8 system on 2004-11-18.
Available extensions:
        GNU libio by Per Bothner
        crypt add-on version 2.1 by Michael Glad and others
        linuxthreads-0.10 by Xavier Leroy
        The C stubs add-on version 2.1.2.
        GNU Libidn by Simon Josefsson
        BIND-8.2.3-T5B
        libthread_db work sponsored by Alpha Processor Inc
        NIS(YP)/NIS+ NSS modules 0.19 by Thorsten Kukuk
Thread-local storage support included.
For bug reporting instructions, please see:
.

ผลการแสดงโปรเซสก่อน NPTL

$ pstree -p 1128
firefox-bin(1128)---firefox-bin(1132)-+-firefox-bin(1133)
                                      `-firefox-bin(1135)

ผลการแสดงโปรเซสเมื่อใช้ NPTL

$ pstree -p 7866
firefox-bin(7866)---netstat(7911)
$ ps -Lp 7866
  PID   LWP TTY          TIME CMD
 7866  7866 pts/0    00:00:08 firefox-bin
 7866  7870 pts/0    00:00:00 firefox-bin
 7866  7872 pts/0    00:00:00 firefox-bin
คือโปรเซสมีโปรเซสเดียวแต่มีหลาย thread (LWP) อยู่ข้างในครับ.
NPTL - Thursday, November 18, 2004 -

Bruce Perens' Open Source series

ที่อยู่ใหม่ของ Poonlap's Linux blog : http://mm.co.th/poonlap

อยากจะพูดถึงชุดหนังสือ Bruce Perens' Open Source series. หนังสือชุดนี้ออกเป็นชุดโดยสำนักพิมพ์ Prentice Hall เห็นบอกว่าให้ Bruce Perens เป็นบรรณาธิกรณ์ของชุดหนังสือนี้. แถมหนังสือแต่ละเล่มใช้หนังสืออนุญาติแบบ Open Public license มีก็อปปี้เป็น PDF ให้ดาว์นโหลดด้วยทุกเล่ม. แต่ตอนนี้เท่าที่ดูยังมีให้ดาว์นโหลดไม่ครบครับ. เห็นสำนักพิมพ์เขียนไว้บอกว่าให้ดาว์นโหลดหนังจากหนังสือออกเรียบร้อยแล้ว. วันนี้ไปเยี่ยมชมเว็บนั้นอีกทีมีให้ดาว์นโหลดเยอะกว่าเมื่อวานตั้งหลายเล่ม.

น่าอ่านและเก็บมากครับ.

Bruce Perens' Open Source series - Tuesday, November 16, 2004 -

ลองดู Firefox Smart search

ที่อยู่ใหม่ของ Poonlap's Linux blog : http://mm.co.th/poonlap


ลองดูนี่ชื่อดิกชันนารีครับ. ยิ่งใช้ firefox นี่ยิ่งเจ๋ง. เขียนวิธีใช้ longdo กับ popthai ไว้ที่ plone ครับ.

ลองดู Firefox Smart search - -

Smart Keywords

ที่อยู่ใหม่ของ Poonlap's Linux blog : http://mm.co.th/poonlap

Smart Keywords เป็นคุณสมบัติอย่างหนึ่งไว้สำหรับพิมพ์คีย์เวิร์ดที่ต้องการลง address bar เลย. รู้สึกว่าสะดวกดี. ตอนนี้คีย์เวิร์ดที่ใช้บ่อยๆได้แก่.
  • tlwg ไปที่ http://linux.thai.net
  • tlwg planet ไปที่ http://linux.thai.net/planet
  • tlwg wwwboard ไปที่บอร์ดเก่า
  • tlwg phpbb ไปที่ http://thaigate.nii.ac.jp/phpBB2/viewforum.php?f=4
  • tlwg plone ไปที่ http://linux.thai.net/plone/TLWG/thailatex/
  • tlwg irc ไปที่ http://linux.thai.net/wwwboard/devel/msg05787.php
  • linux tle ไปที่ http://opentle.org/
ใช้ได้ระดับหนึ่งครับ. สมมติว่าจะไป Tlwg Planet ก็กด Ctrl+l, พิมพ์ "tlwg planet" กด Enter ก็ถึงที่เลย.
Smart Keywords - Friday, November 12, 2004 -

เปลี่ยน key-binding ของ firefox

ที่อยู่ใหม่ของ Poonlap's Linux blog : http://mm.co.th/poonlap

จริงแล้วผมใช้ mozilla อ่านเว็บกับ mozilla mail อ่านเมลมาตลอดเพราะความเคยชิน. ช่วงนี้เริ่มเปลี่ยนมาเป็น "จิ้งจอกไฟ" กับคู่หู "วิหกสายฟ้า" ไม่ค่อยถนัดเพราะปรกติใช้ key-binding ของ emacs ได้เช่น C-a ก็จะไปที่ต้นบรรทัด, C-k ก็จะลบบรรทัดที่เขียนอยู่. ค้นหาข้อมูลจากอินเทอร์เน็ตได้ความจาก Emacs Keybindings (Firefox) ว่าถ้าใช้ gtk2.0 อยู่ก็ใส่คำว่า gtk-key-theme-name = "Emacs" ในไฟล์ .gtkrc-2.0. ลองแล้วไม่เห็นได้เลย. เลยเอาอีกแบบหนึ่งคือไปแก้ที่ Keyboard shortcut ของ Gnome เลย. จาก เมนู Desktop Preferences > Keyboard Shortcuts แล้วระบุให้ใช้ emacs เป็น key-binding แทนค่าปริยายของ Gnome.

อีกวิธีหนึ่งคือไปแก้ที่ไฟล์ res/builtin/platformHTMLBindings.xml ซึ่งมักจะอยู่ที่ในไดเรกทอรีไลบรารีของโปรแกรมตระกูล mozilla แต่ละตัว. อย่างในระบบของผมเป็นแบบนี้.

$ locate platformHTMLBindings.xml
/usr/lib/mozilla/res/builtin/platformHTMLBindings.xml
/usr/lib/MozillaFirefox/res/builtin/platformHTMLBindings.xml
/usr/lib/MozillaThunderbird/res/builtin/platformHTMLBindings.xml
เป็นไฟล์ XML อ่านแล้วเข้าใจได้. เนื้อหาบางอย่างเดาได้ว่าคืออะไร. ที่ไม่เข้าใจคงต้องไปหาข้อมูลเพิ่มเติม.

โอเพนซอร์สก็ดีอย่างนี้แหละคือแก้ได้ถ้าตัวเองไม่ชอบ.

เปลี่ยน key-binding ของ firefox - Thursday, November 11, 2004 -

กระแส firefox

ที่อยู่ใหม่ของ Poonlap's Linux blog : http://mm.co.th/poonlap

เดี๋ยวนี้รู้สึกว่ากระแส firefox แรงมากๆรู้สึกว่าหลายคนกล่าวถึงกันหนาหู. พูดถึงวันก่อนที่เคยอ่านจาก slashdot ว่า firefox เริ่มกลายมาเป็น platform ไปแล้วกระโดดตัวจากเบราว์เซอร์ธรรมดาไปอีกขั้น. วันนี้ไปดู firefox extension ก็เห็นมี extension โน่นนี่มากมายน่าใช้ทั้งนั้น. คุณ bact ก็เคยทำ extension สำหรับเปิดศัพท์ภาษาอังกฤษจาก Longdo ไว้ด้วย.

ว่าไปแล้วมีไอเดียอยากทำ extension บ้างเลยไปหาข้อมูลจากอินเทอร์เน็ต. ไปเจอ Creating Firefox extensions เป็น tutorial สอนทำ Hello world แบบง่ายๆ. คนเขียน tutorial เขาทำ firefox extension ไว้มากมายทีเดียว. เริ่มเข้าใจหลักการแล้วว่าเจ้า firefox extension มันเป็นอย่างไร. เวลาสร้าง extension จะใช้ XUL (XML User Interface Language) เขียนอินเทอร์เฟสกับ Javascript ช่วยด้วย. น่าลองมากๆ. สมควรเรียกว่าเป็น platform จริงๆ.

เพิ่มเติม:
คุณกำธรแนะมาว่า Google สนับสนุนเต็มที่ด้วย. ดูได้จาก http://www.google.com/firefox

กระแส firefox - Wednesday, November 10, 2004 -

The computer technology document project

ที่อยู่ใหม่ของ Poonlap's Linux blog : http://mm.co.th/poonlap

Blog ของผมนับวันจะกลายเป็นแนะนำเว็บไซด์ไปเรื่อยๆแล้ว. วันนี้ไปเจอเว็บชื่อ The computer technology document project. ดูๆไปเรื่อยมีข้อมูลตั้งแต่เบื้องต้นมากเช่นการใช้ Outlook 2000 จนถึงค่อนข้างลึกอย่าง Linux startup เป็นต้น. จัดเนื้อหาเป็นระเบียบดีครับ, ชอบ.
The computer technology document project - Tuesday, November 09, 2004 -

Time

ที่อยู่ใหม่ของ Poonlap's Linux blog : http://mm.co.th/poonlap

วันนี้ลองตั้งโดยเวลาโดยให้ sync (syncronize) กับ ntp เซิฟร์เวอร์ที่อื่น. การตั้งเวลาให้ตรงกับ ntp เซิฟร์เวอร์มีความสำคัญมากโดยเฉพาะอย่างยิ่งถ้ามีเครืื่องคอมพิวเตอร์หลายๆเครื่องอยู่ในเครือข่ายเดียวกัน. สมมติว่าถ้าเครื่องคอมฯเครื่องใดเครื่องหนึ่งในเครือข่ายถูกแคร็ก (crack), บางทีอาจจมี hint หรือข้อความต่างๆในล็อก (log). ถ้าเวลาของเครื่องนั้นไม่เที่ยงตรงก็จะไม่รู้เลยว่าจริงๆแล้วเกิดอะไรขึ้นเมื่อไหร่. สำหรับวินโดว์ส XP นี่รู้สึกทำง่ายมากแค่เช็คให้มัน sync กับ time.windows.com ก็ได้แล้ว.

เครื่องที่ใช้ตอนนี้เป็น Gentoo ก็ทำการ sync เวลาได้ง่ายไม่แพ้กันโดยติดตั้งแพกเกจ ntp.

# emerge ntp
เครื่องที่ใช้อยู่ตอนนี้ไม่ต้องการทำเป็น ntpd เซิฟร์เวอร์, แค่ต้องการตั้งเวลาให้ตรงเท่านั้น. แพกเกจ ntp ของ Gentoo จะมี init script สำหรับเครื่องที่ต้องการเป็นแค่ client ก็แค่เพิ่มสคริปต์ ntp-client ใน default level.
# rc-update add ntp-client default
ตอนบูตเครื่องสคริปต์ ntp-client จะทำงานแล้วใช้คำสั่ง ntpdate ตั้งเวลาให้ตรงกับ ntpd เซิฟร์เวอร์ที่ pool.ntp.org.

pool.ntp.org เป็นชื่อ DNS ที่มอบหมาย ntpd เซิฟร์เวอร์สาธารณะแบบสุ่มให้แต่ละครั้ง. สังเกตดูว่า ntpd เซิฟร์เวอร์ที่ไป sync ด้วยแต่ละครั้งจะไม่เหมือนกัน.

# ntpdate pool.ntp.org
Looking for host pool.ntp.org and service ntp
host found : ntp1.esat.net
 8 Nov 21:52:33 ntpdate[27067]: adjust time server 193.120.142.71 offset 0.336044 sec
# ntpdate pool.ntp.org
Looking for host pool.ntp.org and service ntp
host found : capsicum.zgp.org
 8 Nov 21:53:08 ntpdate[27082]: adjust time server 198.144.202.250 offset 0.152746 sec
Time - Saturday, November 06, 2004 -

Two books today

ที่อยู่ใหม่ของ Poonlap's Linux blog : http://mm.co.th/poonlap

วันนี้ไปเจอมาสองเล่มครับ.

Two books today - Friday, November 05, 2004 -

Howstuffworks

ที่อยู่ใหม่ของ Poonlap's Linux blog : http://mm.co.th/poonlap

ค้นโน่นค้นนี่, เลยไปเจอเว็บหน้าสนใจอันหนึ่งคือ HowStuffWorks เป็นเว็บอธิบายการทำงานของสิ่งต่างๆเช่น GPS ทำงานอย่างไร, เอ็กซ์เรย์ทำงานอย่างไร, หน่วยประมวลผลทำงานอย่างไร, ระบบปฏิบัติการทำงานอย่างไร, ภาษาซีทำงานอย่างไร ฯลฯ. ชอบตรงที่เนื้อหาและการนำเสนอรูปภาพประกอบดีครับ, เป็น animation ทำให้เข้าใจง่าย, แบ่งหมวดหมู่ไว้ดี. เสียอย่างเดียวรู้สึกว่าไซด์นี้ช้าไปนิดหนึ่ง.
Howstuffworks - Thursday, November 04, 2004 -


 
Search this blog:


Google Home - Blogger - Blogger Templates

© 2005 Poonlap's Linux blog