Lect06 ตอนที่ ๑ แฟ้มแทนอุปกรณ์ (Device Files) ---------------------------------- ระบบปฏิบัติการ Unix ได้รับการออกแบบให้สามารถเข้าถึง อุปกรณ์ต่างๆ ในระบบได้ได้โดยเป็นอิสระจากสถาปัตยกรรมของหน่วยประมวลผลกลาง และเพื่อให้การทำงานกับอุปกรณ์ต่างๆ ทำได้ง่าย จึงออกแบบให้ "การเข้าถึง" อุปกรณ์ใดๆ ทำได้โดยใช้ชุดคำสั่งเดียวกัน กล่าวอีกนัยหนึ่งคือ เป็นการเข้าถึงอุปกรณ์ที่แตกต่างกัน โดยใช้ชุดคำสั่งเดียวกัน จึงต้อง "สุมมุติ" แนวคิดที่เป็นนามธรรมเพื่อใช้แทนอุปกรณ์ สิ่งที่สมมุติขึ้นนี้เรียกว่าแฟ้มแทนอุปกรณ์ หรือ device file ที่กำหนดให้เป็นแฟ้มเพราะระบบปฏิบัติการมีบริการในรูปของ system call สำหรับดำเนินการกับแฟ้มอยู่แล้ว แฟ้มแทนอุปกรณ์ หรือ device file ทำหน้าที่เป็นตัวต่อประสาน (interface) ระหว่างระบบปฏิบัติการ และโปรแกรมขับอุปกรณ์ (device driver) โดยกำหนดให้มีลักษณะคล้ายกับแฟ้มปรกติ และจัดเก็บไว้ไดเรกทอรี /dev แบ่งเป็นสองประเภทคือ - Character device file: ใช้แทนอุปกรณ์ที่มีการรับ-ส่งข้อมูลในระดับไบต์ การดำเนินการแต่ละครั้งอาจทำได้ครั้งละหลายไบต์ ไม่จำเป็นต้องจัดหน่วยความจำพักข้อมูล (buffer) เช่น แฟ้มแทนชุดแป้นพิมพ์และจอภาพ (terminal - อุปกรณ์ tty) ใน /dev มีคุณลักษณะที่แสดงในคำสั่ง ls -l เช่น crw--w---- 1 root tty 4, 0 Feb 6 08:47 tty0 # ชนิดของแฟ้มเป็น c - character device และเทอร์มินอลจำลอง (virtual terminal) ที่ได้จากการทำงานของโปรแกรม terminal emulator ในไดเรกทอรี /dev/pts เช่น crw--w---- 1 jira tty 136, 6 Feb 9 18:45 6 - Block device file: ใช้สำหรับอุปกรณ์ที่มีการรับ-ส่งข้อมูลเป็นกลุ่ม (block) จึงต้องมีการจัดหน่วยความจำสำหรับพักข้อมูล (buffer) ซึ่งหมายความว่าจะมีการอ่านข้อมูลจากอุปกรณ์จริงเมื่อข้อมูลใน buffer หมด และมีการเขียนลงอุปกรณ์เมื่อข้อมูล เต็ม buffer เช่น จานแม่เหล็ก มีรายการใน /dev เช่น brw-rw---- 1 root disk 8, 1 Feb 6 08:47 sda1 หมายเหตุ: ตัวเลขหลังชื่อกลุ่ม เช่น 136, 6 ไม่ใช่ขนาดของแฟ้ม แต่เป็นหมายเลขอุปกรณ์ major และ minor device number อุปกรณ์รับข้อมูลเข้าและแสดงผลอย่างง่ายคือแป้นพิมพ์และจอภาพ ซึ่งโดยทั่วไปมักจัดรวมเข้ากับช่องทางสื่อสารแบบอนุกรมรวมเป็นอุปกรณ์เดียวกัน เรียกว่า อุปกรณ์ Teletype (teletypewriter) นิยมเรียกชื่อย่อว่า tty ซึ่งในปัจจุบันไม่มีการผลิตและใช้งานแล้ว เพราะสามารถใช้โปรแกรมจำลองการทำงานได้ เรียกว่าโปรแกรม terminal emulator และระบบมองเห็นเป็น pseudo terminal (pty) การตรวจสอบชื่อแฟ้มของ terminal ที่เชื่อมต่อกับช่องทางรับข้อมูลมาตรฐาน ทำได้โดยใช้คำสั่ง tty เช่น $ tty /dev/pts/0 # แฟ้มแทน virtual terminal การทำงานของโพรเซสจำเป็นต้องมี terminal สำหรับทำงาน จะเห็นได้จากคำสั่ง ps และ who ดังนี้ # ขอดูสถานะของโพรเซสอย่างย่อ $ ps PID TTY TIME CMD 32082 pts/0 00:00:00 bash # โพรเซสที่สร้างจากโปรแกรม bash ทำงานจาก pts/0 32172 pts/0 00:00:00 ps # ซึ่งเป็น pseudo terminal # ขอดูรายชื่อผู้ใช้ที่กำลัง login อยู่ในขณะนี้ $ who jira pts/0 2013-11-23 11:06 (223.204.248.17) หมายเหตุ: โปรแกรมขับอุปกรณ์ หรือ device driver เป็นโปรแกรมที่ใช้ควบคุมการทำงานของอุปกรณ์เฉพาะชนิดที่ติดตั้งในระบบคอมพิวเตอร์ที่ใช้งาน อุปกรณ์บางอย่างมี device driver มาพร้อมกับระบบปฏิบัติการ เมื่อผู้ใช้ซื่ออุปกรณ์ใหม่ที่ระบบยังไม่รู้จักมาติดตั้ง ผู้ใช้ต้องติดตั้งโปรแกรม device driver สำหรับอุปกรณ์นั้น เพื่อทำหน้าที่เปลี่ยนคำสั่ง input/output ที่ระบบปฏิบัติการใช้งานโดยทั่วไป เป็นคำสั่งเฉพาะ สำหรับการทำงานของอุปกรณ์นั้น ตอนที่ ๒ ความสัมพันธ์ระหว่าง file descriptor, file structure และ i-node ----------------------------------------------------------------- ทุกครั้งที่มีการเปิดแฟ้มเพื่อใช้งาน ระบบปฏิบัติการจะเก็บรายละเอียดของแต่ละแฟ้ม เช่น สถานะของแฟ้ม และ ตำแหน่งปัจจุบันของข้อมูลในแฟ้ม เป็นต้น โดยเก็บไว้ในโครงสร้างข้อมูล และจัดโครงสร้างเหล่านี้เป็น array of structures เรียกว่า open file table นอกจากนี้ยังจัด array คู่ขนานสำหรับเก็บ inode ของแฟ้มเหล่านั้นไว้ด้วย เรียกว่า inode table เมื่อมีการการสร้างโพรเซสใหม่ และโพรเซสมีการเปิดใช้งานแฟ้ม ระบบปฏิบัติการจะเพิ่มโครงสร้างข้อมูล และ inode ของแฟ้มนั้นใน open file table และ inode table ของระบบตามลำดับ และสร้างตารางเก็บดัชนีไปยังแฟ้มที่โพรเซสนั้นเปิดในตารางของระบบ ตารางดัชนีแฟ้มที่เปิดของแต่ละโพรเซสนี้ เรียกว่า File descriptotr table ดังแผนภาพ File descriptor table open file table i-node table +---------+ +---------+ +---------+ | | ----------------> | | ----------------> | | +---------+ +---------+ +---------+ | | -----+ | | | | +---------+ \ +---------+ +---------+ | | \ | | | | +---------+ \ +---------+ +---------+ | | +------> | | ------------------> | | +---------+ +---------+ +---------+ | | | | | | +---------+ +---------+ +---------+ สำหรับแต่ละโพรเซส สำหรับแฟ้มทั้งหมด ตารางเก็บ i-node ที่มีการเปิดใช้งาน ที่สมนัยกับแฟ้มที่เปิดอยู่ array of pointers array of file structures array of i-nodes เก็บดัชนี (นิยมเรียกว่า เป็น array ของโครงสร้าง ของแฟ้มทุกแฟ้มที่เปิดอยู่ pointer) ของตาราง ข้อมูลที่ใช้เก็บตำแหน่ง ในตาราง open file table open file table ในแฟ้มที่จะมีการอ่าน/เขียน ตำแหน่งของ i-node และ เฉพาะแฟ้มที่โพรเซส ในลำดับ ต่อไป สถานะของ ile structure อยู่ในตำแหน่ง เปิดใช้งาน - ดัชนีของ แฟ้ม แต่ละแฟ้มมีโครงสร้าง ตรงกัน ตารางนี้เรียกว่า ข้อมูลแยกจากกัน ตารางนี้ file descriptor จึงเป็น array ของโครงสร้าง ข้อมูลของทุกแฟ้มที่มีการ เปิดใช้งานในระบบในขณะนั้น หมายเหตุ: การอ้างอิงแฟ้มที่เปิดใช้งานของระบบปฏิบัติการ Unix และโปรแกรมภาษา C มีความแตกต่างกัน คือ ระบบปฏิบัติการ Unix อ้างอิงโดยใช้ file descriptor ซึ่งเป็นจำนวนเต็มสำหรับระบุแฟ้มที่มีการเปิดใช้งาน หรือใช้เป็น file handle ในการเรียกใช้ system calls ซึ่งเป็นบริการที่ระบบปฏิบัติการมีให้ผู้ใช้ในการพัฒนาโปรแกรมประยุกต์ เช่น read(), write() ซึ่งเป็นบริการ "ดิบ" ดำเนินการกับแฟ้มโดยตรง ไม่มี buffer ส่วนโปรแกรมภาษา C อ้างอิงโดยใช้ file pointer ซึ่งเป็น pointer ที่ชี้ไปยังโครงสร้างข้อมูลของแฟ้มที่กำหนดใน Library ของ C เป็นโครงสร้างข้อมูลที่มีการจัด buffer และมีการกำหนดคุณลักษณะเพิ่มเติม เพื่อทำให้ การทำ input/output ง่ายขึ้นใช้งานร่วมกับฟังก์ชันมาตรฐานของ C เช่น fread(), fwrite() ตอนที่ ๓ Standard File ----------------------- เมื่อระบบปฏิบัติการสร้างโพรเซส ระบบจะจัดเตรียมช่องทางสำหรับติดต่อกับอุปกรณ์ภายนอก โดยต้องมีช่องทางสำหรับรับข้อมูลเข้า (input), ช่องทางสำหรับแสดงผลลัพธ์ (output) และช่องทางสำหรับแสดงความผิดพลาด (error message) โดยระบบจะเตรียมแฟ้มมาตรฐานไว้ให้สามแฟ้มดังนี้คือ - standard input หรือ stdin สำหรับรับข้อมูลจากอุปกรณ์ภายนอกเข้าสู่โพรเซส - standard output หรือ stdout สำหรับส่งผลลัพธ์ของโพรเซสออกสู่อุปกรณ์ภายนอก - standard error หรือ stderr สำหรับส่งข่าวสารแสดงความผิดพลาดที่อาจเกิดขึ้นในโพรเซสออกสู่อุปกรณ์ภายนอก แฟ้มทั้งสามคือ stdin, stdout และ stderr มี file descriptor เป็น 0, 1 และ 2 ตามลำดับ แฟ้มทั้งสามนี้เป็นชื่อของแฟ้มแทนอุปกรณ์ จึงเป็นเพียงตัวกลางสำหรับเชื่อมโพรเซสเข้ากับอุปกรณ์จริง และระบบปฏิบัติการจะเชื่อมแฟ้มทั้งสามเข้ากับอุปกรณ์ดังนี้ แป้นพิมพ์ ---------- \ stdin (0) \ ------------ โพรเซส stderr (2) / / / / stdout (1) จอภาพ -------------- หมายเหตุ ตัวเลขในวงเล็บคือ file descriptor แฟ้มอื่นนอกเหนือจากสามแฟ้มนี้ ผู้ใช้ต้องดำเนินการเอง ค่าโดยปริยายของ Linux กำหนดให้โพรเซสเปิดแฟ้มพร้อมกันได้สูงสุดไม่เกิน 32 แฟ้ม การเปลี่ยนแปลงจำนวนแฟ้มที่เปิดได้สูงสุดนี้เป็นสิทธิของผู้ดูแลระบบ และในระบบปฏิบัติการ Unix, file descriptor 0, 1, 2 กำหนดไว้เป็น symbolic constants ในชื่อ STDIN_FILENO, STDOUT_FILENO, และ STDERR_FILENO สำหรับชื่อ stdin, stdout, stderr เป็นชื่อของ standard stream ในภาษา C ซึ่งเป็น pointers ไปยังโครงสร้างข้อมูล หรือ FILE * ตอนที่ ๔ การเปลี่ยนทิศทาง ( input/output redirection ) -------------------------------------------------- เนื่องจาก stdin, stdout และ stderr เป็นแฟ้มแทนอุปกรณ์ซึ่งเป็นตัวกลางเชื่อมโพรเซสกับอุปกรณ์ภายนอก เมื่อเชื่อมต่อกับแป้นพิมพ์และจอภาพ ซึ่งเป็นแฟ้มแทนอุปกรณ์ได้ ก็ควรเชื่อมต่อกับแฟ้มธรรมดาได้ก็เช่นเดียวกัน วิธีการนี้เรียกว่าการเปลี่ยนทิศทาง input/output ซึ่งมี operator ดังนี้ operator การดำเนินการ ------------- --------------------------------------------------------- 0< หรือ 0 เปลี่ยนทิศทาง input จากแป้นพิมพ์ เป็นข้อมูลจากแฟ้ม > หรือ 1> เปลี่ยนทิศทาง output จากจอภาพ ไปยังแฟ้ม 2> เปลี่ยนทิศทาง error จากจอภาพ ไปยังแฟ้ม >> เปลี่ยนทิศทาง output จากจอภาพไปยังแฟ้ม และเขียนข้อมูลใหม่ต่อท้ายข้อมูลเดิม (append) 2>&1 เปลี่ยนทิศทาง error จากจอภาพไปยังแฟ้มเดียวกับที่กำหนดไว้เป็นแฟ้มสำหรับ output รูปแบบการใช้งาน $ คำสั่ง [-option] [argument-list] outputfile ตอนที่ ๕ Unix Pipeline --------------------- ในระบบปฏิบัติการ Unix คำว่า pipeline (หรือ software pipeline -- hardware pipeline เป็นสถาปัตยกรรมของหน่วยประมวลผลกลาง) หมายถึงกลุ่ม (set) ของโพรเซสที่มีการเชื่อมต่อกันผ่าน standard stream กล่าวคือ standard output ของโพรเซสหนึ่งต่อเข้ากับ standard input ของอีกโพรเซสหนึ่ง (เชื่อมต่อกันด้วย anonymous pipe) โปรแกรมที่อยู่ใน pipeline ส่วนใหญ่เป็นโปรแกรมในกลุ่มที่เรียกว่า Filter คือโปรแกรมที่รับข้อมูลจาก standard input ส่งผลลัพธ์ออกทาง standard output -- คำอธิบายอีกแบบหนึ่ง -- ผู้ใช้สามารถสั่งให้คำสั่งสองคำสั่งทำงานร่วมกันได้ โดย output ของคำสั่งที่อยู่หน้าจะถูกส่งเป็น input ของอีกคำสั่งหนึ่งที่อยู่ถัดไป คำสั่งตั้งแต่สองคำสั่งขึ้นไปที่มีการใช้งานในลักษณะนี้เรียกว่า pipeline และเรียกการเชื่อมต่อระหว่างคำสั่งว่า pipe แทนด้วยเครื่องหมาย vertical bar (|) โปรแกรมหรือคำสั่งที่รับ input จากโปรแกรมอื่นมาดำเนินการและส่งผลลัพธ์ออกทาง standard output (stdout) เรียกว่า filter รูปแบบการใช้งาน ------------- $ คำสั่งแรก | คำสั่งที่ 2 | ... | คำสั่งที่ n คัวอย่างที่ ๑ --------- $ ls -l | grep key | more เครื่องหมาย | เรียกว่า vertical bar หรือที่นิยมเรียกมากกว่าคือ pipe character เป็น operator มีคุณสมบัติเป็น left associative infix operation ซึ่งโดยปกติ standard error stream (stderr) จะไม่มีการส่งผ่านไปใน pipeline แต่จะส่งออกสู่ console หากต้องการรวม stdout และ stderr ใน stream เดียวกัน สำหรับ bash ทำได้โดย 2>&1 เช่นเดียวกับการทำ redirection ตัวอย่างที่ ๒ --------- ต้องการพิมพ์ข้อมูลบรรทัดที่ 25 - 75 จากแฟ้มชนิด text file $ cat file | head -75 | tail -50 head รับข้อมูลทั้งแฟ้มจาก cat และแยกเฉพาะข้อมูล 75 บรรทัดแรก จากนั้นจึงส่งต่อให้ tail ซึ่งจะทำการแยกเฉพาะข้อมูล 50 บรรทัดนับจากบรรทัดสุดท้ายขึ้นมา แสดงผลทางจอภาพ ตัวอย่างที่ ๓ ---------- ผู้สอนสั่งให้โปรแกรม top ทำงานผ่าน virtual terminal ที่ห้องพัก และเข้าสอน เมื่อสอนไปได้ระยะหนึ่งผู้ดูแลระบบส่งข่าวมาเตือนว่าขอให้เลิกทำงานและ logout เพราะต้องการปิดระบบเพื่อบำรุงรักษา ผู้สอนสามารถสั่งฆ่าโพรเซสได้จาก virtual terminal ในห้องเรียน โดยใช้คำสั่ง ps -ef เพื่อดูสถานะของโพรเซส $ ps -ef UID PID PPID C STIME TTY TIME CMD ... ... ... ... ... .. ... ... ... ... ... ... ... ... ... ... ... ... ... ... jira 14080 13613 0 16:02 pts/1 00:00:00 top -u jira -d 100.0 ... ... ... ... ... .. ... ... ... ... ... ... ... ... ... ... ... ... ... ... จะได้ว่าโพรเซสของ top มีหมายเลขโพรเซส (process identification - pid) เป็น 13730 เมื่อได้หมายเลขโพรเซสแล้ว สามารถทำลายโพรเซสได้ด้วยคำสั่ง kill เช่น $ kill -9 <หมายเลขโพรเซส> ต้องการทำลายโพรเซสจากชื่อของโปรแกรม -- ทำได้โดยใช้ pipelining $ ps -ef | grep top | grep -v grep | awk '{print $2}' | xargs kill -9 รายละเอียดของคำสั่งเป็นดังนี้ --------------------- 1. ps -ef เป็นการแสดงโพรเซสทั้งหมดในระบบ โดยแสดงหมายเลขโพรเซส (pid) ในคอลัมน์ที่สอง $ ps -ef UID PID PPID C STIME TTY TIME CMD ... ... ... ... ... .. ... ... ... ... ... ... ... ... ... ... ... ... ... ... jira 14080 13613 0 16:02 pts/1 00:00:00 top -u jira -d 100.0 ... ... ... ... ... .. ... ... ... ... ... ... ... ... ... ... ... ... ... ... 2. นำ output ของ ps -ef ส่งเป็น input ให้กับ grep เพื่อแสดงเฉพาะบรรทัดที่มีคำว่า 'top' ซึ่งเป็นชื่อของโปรแกรมที่ต้องการ $ ps -ef | grep top jira 14080 13613 0 16:02 pts/1 00:00:00 top -u jira -d 100.0 jira 14250 13472 0 16:11 pts/0 00:00:00 grep top ผลลัพธ์มีสองบรรทัดคือ บรรทัดโพรเซสของคำสั่ง top -u jira -d 100.0 (ซึ่งเป็นบรรทัดที่ต้องการ) และบรรทัดโพรเซสของคำสั่ง grep top (ซึ่งเป็นบรรทัดที่ไม่ต้องการ) 3. กำจัดบรรทัดโพรเซสของ grep โดยใช่ grep -v grep (option -v -- invert-output แสดงบรรทัดที่ไม่มีคำว่า grep) $ ps -ef | grep top | grep -v grep jira 14080 13613 0 16:02 pts/1 00:00:00 top -u jira -d 100.0 4. เมื่อได้เฉพาะบรรทัดโพรเซสของ top แล้ว ทำการแยก pid ซึ่งอยู่ในคอลัมน์ที่สองออกด้วย awk $ ps -ef | grep top | grep -v grep | awk '{print $2}' 14080 awk เป็นภาษาสำหรับตรวจหา pattern และประมวลผล เป็นภาษาที่มีประสิทธิภาพในการทำงานสูงมาก และมี่รายละเอียดในการใช้งานสูงมากเช่นกัน หากสนใจศึกษารายละเอียดได้จาก eBook ที่กำหนดเป็นหนังสืออ้างอิง คำสั่ง $ awk '{print $2}' กำหนดให้พิมพ์ข้อมูลในคอลัมน์ที่สองของข้อมูลที่ได้รับทาง stdin ออกทาง stdout 5. ส่ง pid ที่ได้เป็น argument ของคำสั่ง kill -9 โดยใช้ xargs $ ps -ef | grep top | grep -v grep | awk '{print $2}' | xargs kill -9 $ ที่ pts/1 ซึ่งเป็น virtual terminal จะแสดงข้อความ Killed และแสดง prompt เพื่อรับคำสั่งต่อไป killed $ หมายเหตุ ------- คำสั่งในข้อ 5 สามารถนำมาเขียนเป็น shell script (สมมุติว่าชื่อ mykill) และกำหนดให้รับชื่อโปรแกรมผ่าน parameter $ cat mykill ps -ef | grep $1 | grep -v grep | awk '{print $2}' | xargs kill -9 เมื่อ $1 เป็น command line argument ตัวแรก และสามารถเรียกใช้งานได้ดังนี้ $ mykill top ความแตกต่างระหว่าง redirection และ pipeline ---------------------------------------- ความแตกต่างที่สำคัญระหว่าง output redirection (>) และ pipeline (|) อยู่ที่ปลายทาง > ปลายทางเป็น "แฟ้ม" duplicate file descriptor | ปลายทางเป็น "โพรเซส" open pipes Utilities ที่ใช้เฉพาะกับ redirection และ pipeline ----------------------------------------- Utilities ที่ใช้เฉพาะกับ redirection และ pipeline ได้แก่คำสั่ง tee และ xargs tee - read from standard input and write to standard output and files ------------------------------------------------------------------- tee เป็นโปรแกรมที่ทำหน้าที่อ่านข้อมูลจาก standard input และนำข้อมูลที่อ่านได้ส่งออกทาง standard output และแฟ้มที่กำหนด tee เป็นเหมือนข้อต่อรูปตัว T สำหรับแยกข้อมูลที่ได้ออกเป็น 2 ทาง โดยส่งออกไปทาง standard output ตามปกติทางหนึ่ง และเขียนลงสู่แฟ้มที่กำหนดให้อีกทางหนึ่ง มีรูปแบบการใช้งานดังนี้ $ tee [option] file-list option ที่น่าสนใจคือ -a (append) เขียนข้อมูลต่อท้ายข้อมูลที่มีอยู่เดิมในแฟ้ม ตัวอย่าง $ ls -l /dev/sda /dev/console | tee log crw------- 1 root root 5, 1 Nov 20 18:14 /dev/console brw-rw---- 1 root disk 8, 0 Nov 20 18:14 /dev/sda เป็นคำสั่งขอดูรายละเอียดของแฟ้มแทนอุปกรณ์ 2 แฟ้ม คือ อุปกรณ์ console และ hard drive ชนิด scsi โดยส่งผลที่ได้ผ่าน pipe ไปยัง tee ซึ่งจะทำการคัดลอกข้อมูลที่ได้รับส่งออกเป็นสองทางคือ จอภาพ ซึ่ง เชื่อมต่ออยู่กับ standard output และแฟ้มชื่อ log ตามแผนภาพ stdout stdin stdout | โพรเซสของ ls | -----------> ||||| ---------> | โพรเซสของ tee | ----------> จอภาพ pipe | v แฟ้ม log เมื่อใช้คำสั่ง cat ดูข้อมูลในแฟ้ม log จะเห็นได้ว่าเป็นข้อมูลชุดเดียวกัน $ cat log crw------- 1 root root 5, 1 Nov 20 18:14 /dev/console brw-rw---- 1 root disk 8, 0 Nov 20 18:14 /dev/sda xargs - build and execute command lines from standard input ----------------------------------------------------------- ในสัปดาห์ที่ 2 เราได้กล่าวถึงการทำ Command Substitution ซึ่งเป็นการนำ "ผลลัพธ์ (output)" ของคำสั่งหรือกลุ่มของคำสั่งมาแทนที่คำสั่งนั้น โดยการกำกับคำสั่งด้วย (`) เช่น $ echo `ls /bin | wc -l` เริ่มทำงานตามคำสั่งที่กำกับด้วยเครื่องหมาย backquote ก่อนคือ `ls /bin | wc -l` ซึ่งเป็นการกำหนดให้ shell ทำการแสดงรายชื่อแฟ้มในไดเรกทอรี /bin และนำผลลัพธ์ที่ได้เป็น input ของโปรแกรม wc ซึ่งกำหนดให้นับเฉพาะจำนวนบรรทัด และส่งจำนวนบรรทัดที่นับได้ออกทาง standard output ซึ่งคำสั่งนี้ให้ผลลัพธ์เป็น 149 ผลลัพธ์นี้จะถูกนำไปแทนคำสั่งใน backquote เป็น $ echo 149 149 ผลลัพธ์ของคำสั่ง $ ls /bin | wc -l 149 หากนำผลที่ได้ส่งผ่าน pipe ไปยังคำสั่ง echo ดังนี้ $ ls /bin | wc -l | echo จะไม่มีการแสดงผลใดเลย ต้องพิจารณาจากรูปแบบของคำสั่ง echo คือ echo [option] message เป็นการนำ message ที่กำหนดออกแสดงทาง standard out และปิดท้ายด้วย newline -- คำสั่ง echo ไม่สามารถรับข้อมูลทาง standard input ได้ (ไม่ใช่คำสั่งในกลุ่ม filter) ดังนั้นเมื่อ wc ส่ง output ผ่าน pipe ไปให้ echo จึงไม่สามารถอ่านได้ จึงเท่ากับคำสั่ง echo มี string ว่างเป็น message ในกรณีนี้เราไม่ต้องการ 149 เป็น standard input ของ echo แต่ต้องการส่ง 149 เป็น message หรือ argument ของคำสั่ง echo ในรูป echo 149 กรณีเช่นนี้สามารถทำได้ โดยใช้คำสั่ง xargs ซึ่งมีรูปแบบการใช้งานอย่างง่ายดังนี้ xargs [option] คำสั่งที่ต้องการใช้งาน pipeline ที่จัดใหม่แล้วเป็นดังนี้ $ ls /bin | wc -l | xargs echo 149 ตัวอย่างนี้ xargs อ่านข้อมูลจากจาก pipe มาใช้เป็น argument ของคำสั่ง echo แล้วจึงให้คำสั่ง echo ทำงาน ตัวอย่างที่ ๒ --------- $ cat apple1.txt Nothing is more practical than a good theory. $ cat apple2.txt Theory without practice is fruitless, but practice without theory is rootless. $ cat aa.txt The apple doesn't far from the tree. I looked at the father, then at the son, and I thought, the apple doesn't fall far from the tree. $ cat bb.txt Compare apples and oranges. To examine the similarities of things that are completely different. Usually used to explain that two things cannot be compared. $ ls | grep apple # output ของ ls เป็นรายชื่อแฟ้ม ดังนั้น input ของ grep apple1.txt # จึงเป็นรายชื่อแฟ้ม, grep จะแยก input ที่มีคำว่า apple apple2.txt # ในชื่อแฟ้มออกทางจอภาพ $ ls | xargs grep apple # output ของ ls เป็นรายชื่อแฟ้ม ซึ่ง xargs ใช้เป็น argument aa.txt:The apple doesn't far from the tree. # ของ grep :- grep apple aa.txt bb.txt aa.txt:the apple doesn't fall far from the tree. # จึงเป็นการพิมพ์บรรทัดในแฟ้ม aa.txt และ bb.txt ที่มีคำว่า bb.txt:Compare apples and oranges. # apple ทางจอภาพ ข้อคิดควรคำนึง ----------- Nothing is more practical than a good theory. ไม่มีอะไรสามารถประยุกต์ใช้งานจริงได้ดีเท่ากับทฤษฎีที่ดี Theory without practice is fruitless, but practice without theory is rootless. ทฤษฏีที่ขาดการปฏิบัตินั้นไร้ผล แต่การปฏิบัติที่ขาดทฤษฏีนั้นไร้ราก