การใช้งาน BASH เบื้องต้น

ผมเขียนบทความนี้ด้วยเจตนาอยากให้มีผู้อ่านหลายระดับ จึงขออภัยหากภาษาที่ใช้ดูฟุ่มเฟือยและอ่อนกำลัง

ลินุกซ์ในความหมายที่แท้จริง เป็นเพียง OS Kernel ที่ทำหน้าที่จัดสรรทรัพยากรต่างๆ ของระบบ ไม่สะดวกที่จะนำมาใช้งานโดยตรง เหล่านักพัฒนาจึงได้สร้างระบบติดต่อ (interactive system) ขึ้นมาครอบลินุกซ์เคอร์เนลเพื่อให้สามารถใช้งานได้สะดวกขึ้น สถาปัตยกรรมลินุกซ์ในปัจจุบันแบ่งออกได้เป็น 4 ระดับชั้น คือ kernel > shell > window manager > desktop environment

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

ต้องขอออกตัวว่าผมเติบโตมาในยุคของ BASH (Bourne-Again Shell) และ GNOME บทความนี้จึงใช้การอ้างอิงจาก BASH และ GNOME Terminal เป็นหลักนะครับ

ก้าวแรก:

shell คือโปรแกรมที่ทำหน้ารับคำสั่งจากผู้ใช้ไปส่งให้เคอร์เนล การติดต่อกับ shell จะติดต่อผ่านโปรแกรมเทอร์มินัลอีกที สำหรับผู้ใช้ GNOME เข้าไปที่ Applications > Accessories > Terminal เมื่อเข้าสู่เทอร์มินัลจะพบกับข้อความลักษณะต่อไปนี้ tonkla@myhost:~$ นั่นหมายถึง shell พร้อมรับคำสั่งแล้ว สามารถดูค่าที่กำหนดรูปแบบการแสดงผลของข้อความ โดยใช้คำสั่ง

$ echo $PS1

ถ้าเป็นลินุกซ์ตระกูล Debian จะได้ผลลัพธ์เป็น

${debian_chroot:+($debian_chroot)}\u@\h:\w\$
  • \u คือชื่อผู้ใช้
  • \h, \H คือชื่อโฮสต์
  • \w คือพาธ (path) ของไดเรกทอรีแบบเต็ม (/a/b/c/d/e)
  • \W คือพาธเฉพาะไดเรกทอรีปัจจุบัน (/e)

ตัวอย่างการเปลี่ยนแปลงรูปแบบการแสดงผลโดยใช้คำสั่ง export

$ export PS1='\H [\W] >'

การเดินทางไปบนถนนสาย "directory":

ตำแหน่งไดเรกทอรีเริ่มต้นเมื่อเข้าสู่เทอร์มินัลคือ Home Directory ของผู้ใช้แต่ละคน การย้ายตำแหน่งไปยังไดเรกทอรีอื่นๆ จะใช้คำสั่ง cd (change directory) ตามด้วยไดเรกทอรีที่ต้องการไป

ดูเนื้อหาภายในไดเรกทอรีปัจจุบันด้วยคำสั่ง ls (list directory contents)

$ ls

อยู่ที่เดิม

$ cd .

ออกไปไดเรกทอรีชั้นนอก 1 ชั้น

$ cd ..

ออกไปไดเรกทอรีชั้นนอก 2 ชั้น

$ cd ../..

สลับไปมาระหว่างสองไดเรกทอรีที่เข้าถึงล่าสุด (ไดเรกทอรีที่เก็บไว้ในตัวแปร $PWD และ $OLDPWD)

$ cd -

กลับบ้าน

$ cd

การใช้งาน cd ในระดับที่สูงขึ้น จะเล่นกับค่าในตัวแปร $CDPATH ยกตัวอย่างเช่น เรามี /a/b/c ถ้าใช้คำสั่ง

$ export CDPATH=.:/a/b

ในกรณีที่อยู่บ้าน (home) แล้วต้องการไปยัง c จะใช้คำสั่งสั้นๆ เพียง

$ cd c

กด Tab ช่วยเติมเต็ม:

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

ย่อคำสั่งด้วยคำสั่ง alias:

เคยเห็นผู้ใช้มือใหม่อีกเช่นกัน เวลาจะดูเนื้อหาในไดเรกทอรีแบบแสดงรายละเอียด จะใช้คำสั่ง

$ ls -l

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

$ alias ll='ls -l'

ต่อไปก็แค่พิมพ์

$ ll

สิ่งที่ซ่อนอยู่:

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

ระบบไฟล์ของลินุกซ์จะใช้จุด . (ขออภัยครับ จำชื่อภาษาไทยสวย ๆ ไม่ได้) นำหน้าไฟล์หรือไดเรกทอรีที่ต้องการซ่อน หากต้องการให้ปรากฏต้องใช้คำสั่ง

$ ls -a

เมื่อลอง ls -a ใน home directory ดู จะพบว่ามีไฟล์และไดเรกทอรีปรากฏมากมาย ส่วนใหญ่จะเป็นไฟล์คอนฟิกกูเรชันสำหรับเก็บค่าต่าง ๆ ของผู้ใช้ไว้ ไฟล์ที่สำคัญต่อการทำงานของ BASH มี 4 ไฟล์ คือ .bash_history, .bash_logout, .bashrc และ .profile

การจะให้ค่าต่างๆ มีผลอย่างถาวร ต้องไปเขียนใส่ไว้ในไฟล์ .bashrc หรือ .profile ลองเปิดดูด้วย text editor ที่ชอบครับ แล้วจะเข้าใจดีขึ้น

ความแตกต่างระหว่างการใส่ไว้ใน .bashrc และ .profile คือ .profile จะให้ผลทันทีที่ล็อกอินเข้าระบบ ตัวอย่างคำสั่งเช่น xrandr เป็นคำสั่งที่ใช้สั่งให้ output ออก 2 จอภาพ ถ้าใส่ไว้ใน .profile จะมีผลทันทีที่ผ่าน GDM Login เข้ามา ส่วน .bashrc จะให้ผลช้ากว่า ต้องมี activity อะไรสักอย่างกับระบบก่อน ค่าปรับแต่งใน .bashrc ถึงจะทำงาน

reuse คำสั่งด้วย history:

คำสั่งต่าง ๆ ที่ถูกพิมพ์ลงไปในเทอร์มินัลและกด Enter แล้ว จะถูกเก็บไว้อยู่ในไฟล์ .bash_history คงจะดีไม่น้อย ถ้าหากเราสามารถเรียกใช้คำสั่งยาว ๆ เหล่านั้นได้อีกครั้งโดยไม่ต้องพิมพ์ใหม่

ดู 100 คำสั่งที่ใช้ล่าสุด

$ history 100

เรียกใช้คำสั่งล่าสุด

$ !!

เรียกใช้คำสั่งที่ 50

$ !50

เรียกใช้คำสั่งล่าสุดที่ขึ้นต้นด้วย xxx

$ !xxx

เรียกใช้คำสั่งล่าสุดที่ประสมด้วย yyy (เช่น $ cd /aaa/bbb/ccc/ddd/eee/fff/xxx/yyy)

$ !?yyy

สามารถดูรายละเอียดเพิ่มเติมได้จาก history manual

$ man history

วิ่งผลัดด้วยสัญลักษณ์ | (pipe):

| คือสัญลักษณ์ที่ใช้เป็นตัวส่งผ่านผลลัพธ์ (output) ของคำสั่งแรก ไปเป็นวัตถุดิบ (input) ของคำสั่งถัดไป เช่น

$ ls -l | grep xxx | more

หมายถึง แสดงผลเนื้อหาในไดเรกทอรีแบบแถวรายละเอียด โดยกรองเอาเฉพาะบรรทัดที่ประสมด้วย xxx และถ้าผลลัพธ์มียาวเกิน 1 หน้าจอ ให้แสดงทีละหน้าจอ

รวบหัวรวบหางด้วย ; (semi-colon):

ปกติเมื่อเข้าไปในไดเรกทอรีอื่นแล้ว เรามักจะล้างหน้าจอ และขอดูรายละเอียดเนื้อหาในไดเรกทอรีใหม่นั้นเสมอ เช่น

$ cd xxx
$ clear
$ ls

จากตัวอย่างเราต้องกด Enter ถึง 3 ครั้ง จะดีกว่าไหมถ้ากด Enter แค่ครั้งเดียว (แต่กดคีย์อื่นแทนอีก 2 ครั้ง -_-')

$ cd xxx; clear; ls

input/output ง่ายๆ ด้วยเครื่องหมาย '>' / '<' :

$ cat > sample.txt
aaa
bbb
Ctrl+d

จากคำสั่งข้างต้น เราจะได้ไฟล์ sample.txt ที่มีเนื้อหา aaa(\n)bbb อยู่ข้างใน (กด Ctrl+d เพื่อบอกว่าจบการเขียน)

ตัวอย่างที่ใช้งานจริง

การสำรองข้อมูล mysql :

$ mysqldump -u root -p your_db > your_backup.sql

การถ่ายคืนข้อมูล mysql :

$ mysql -u root -p your_db < your_backup.sql

ใช้คีย์ลัด:

  • Ctrl+l : Clear Screen
  • Ctrl+u : Undo Typing
  • Ctrl+c : Cancel Task
  • Ctrl+d : Exit
  • ฯลฯ

นึกออกเพียงเท่านี้ครับ ท่านใดนึก trick เล็ก ๆ น้อย ๆ ออก ก็อย่าลืมแบ่งปันกันบ้างนะครับ

อ้างอิง:

Comments

พอดีห่างเน็ตไประยะหนึ่ง บทความนี้เลยรออยู่ในคิวอยู่นาน กว่าจะได้ขึ้นหน้าแรก ต้องขออภัยอย่างแรงครับ

ไม่เป็นไรครับ webmaster ชดเชยให้ด้วยการจัดหน้าใหม่ อย่างงาม ถูกใจมากครับ

ตอนแรกผมกังวลเรื่องภาษาที่ใช้ เช่น เทอร์มินัล, ไดเรคทอรี ฯลฯ ไม่แน่ใจว่าที่ถูกต้องเขียนอย่างไร จะเขียนทับศัพท์เป็นภาษาอังกฤษก็กลัวดูไม่เหมาะสม :-)

ขอชมว่าเขียนได้ดีมากๆ ทั้งการเชิญชวนและการแนะนำ อ่านแล้วเข้าใจได้ง่าย ลองทำแล้วก็ได้ประโยชน์ อยากให้ทราบว่าเนื้อหาเรียบเรียงได้ดีมาก จะรอติดตามงานลำดับต่อไป หากไม่เป็นการรบกวนมากไป อยากให้แนะนำเรื่อง shell script เสียด้วยเลย

ขอบคุณครับ .. คิดๆ เขียนๆ นานเหมือนกันครับ กว่าจะออกมาเป็นรูปแบบนี้ :-)

ส่วนเรื่อง shell script ผมต้องขออภัยที่ผมไม่มีความรู้ครับ ผมเพียงแค่ hack โค้ดง่ายๆ ได้ แต่ถ้าให้เริ่มเขียนเองทั้งหมดไม่สามารถครับ

ดังนั้น .. ผมขอ request บทความเรื่อง shell script จากคุณ "wd" นะครับ :-P

ถ้าให้เขียนแบบมีคุณภาพขนาดนี้ ผมก็ไม่สามารถเหมือนกันครับ

(แต่อาจเขียนแบบกองโจรนะครับ ตามที่เวลาจะอำนวย :)

สนับสนุน shell script ครับ

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

ผมมีปัญหาเกี่ยวกับ การแก้ไขไฟล์ /etc/bash.bashrc ไม่ทราบว่าเวลาใช้

ืsudo nano /etc/bash.bashrc แล้วจะเข้าไปใส่ path ได้ยังไงอะครับ

export JMFHOME /home/lando/JMF-2.1.1e
export CLASSPATH $JMFHOME/lib/jmf.jar:.:${CLASSPATH}
export LD_LIBRARY_PATH $JMFHOME/lib:${LD_LIBRARY_PATH}

มันต้องใช้ if ... fi หรือป่าวแล้วทำไงครับ ขอความช่วยเหลือจากผู้รู้หน่อยครับ

ตกเครื่องหมาย '=' ระหว่างชื่อกับค่าตัวแปรนะครับ ต้องเป็น

export JMFHOME=/home/lando/JMF-2.1.1e
export CLASSPATH=$JMFHOME/lib/jmf.jar:.:${CLASSPATH}
export LD_LIBRARY_PATH=$JMFHOME/lib:${LD_LIBRARY_PATH}

(ไม่มีเว้นวรรคหน้าและหลัง '=')

Creative Commons License ลิขสิทธิ์ของบทความเป็นของเจ้าของบทความแต่ละชิ้น
ผลงานนี้ ใช้สัญญาอนุญาตของครีเอทีฟคอมมอนส์แบบ แสดงที่มา-อนุญาตแบบเดียวกัน 3.0 ที่ยังไม่ได้ปรับแก้