Lecture-04 (New) เนื้อหาการบรรยายในสัปดาห์นี้แบ่งออกเป็น ๓ ตอน; ตอนที่ ๑ เป็นเรื่องการขายความอักขระพิเศษ หรือ meta-character ของเชลล์ ต่อจากสัปดาห์ที่แล้ว, ตอนที่ ๒ เป็นเรื่องการกำหนดสิทธิ setuid, setgid และ sticky bit สำหรับแฟ้ม, และตอนที่ ๓ เป็นเรื่องความแตกต่างระหว่าง text file และ binary file ตอนที่ ๑ การขยายความอักขระพิเศษ หรือ meta-character ของเชลล์ ------------------------------------------------------- การขยายความอักขระพิเศษของเชลล์ (Expansion) ---------------------------------------- เมื่อผู้ใช้ป้อนบรรทัดคำสั่งและกดแป้น เชลล์ต้องดำเนินการกับข้อความในบรรทัดนั้นหลายอย่างก่อนที่จะให้ทำงานตามคำสั่งนั้น เช่น เมื่อเชลล์พบดอกจัน ("*") ซึ่งเป็นอักขระพิเศษที่ใช้แทนอักขระใดๆ จำนวนกี่ตัวก็ได้ในชื่อแฟ้ม เชลล์จะทำการขยาย (expansion) เครื่องหมายดอกจันออกเป็นชื่อแฟ้มที่ตรงกับความหมายของดอกจัน ก่อนที่จะดำเนินการกับแฟ้มนั้นตามคำสั่งที่กำหนด การขยายความอักขระพอเศษของเชลล์ (expansion) มีหลายแบบ ดังจะได้กล่าวถึงเป็นลำดับไป การขยายชื่อแฟ้มและเส้นทางไปยังแฟ้ม (Pathname expansion) ------------------------------------------------- Wild card ในชื่อแฟ้ม; ?, *, ~, [...], {...} ---------------------------------------- $ echo Hello world Hello world $ echo * รายชื่อแฟ้มทั้งหมดในไดเรกทอรีปัจจุบัน แทนที่จะแสดงเครื่องหมายดอกจัน คำสั่ง echo * แสดงรายชื่อแฟ้มทั้งหมดในไดเรกทอรี เพราะเครื่องหมายดอกจัน (*) เป็นอักขระพิเศษที่หมายถึงอักขระใดๆ จำนวนเท่าใดก็ได้ในชื่อแฟ้ม เชลล์จึงขยายเครื่องหมายดอกจันออกเป็นชื่อแฟ้มทุกแฟ้มในไดเรกทอรีปัจจุบัน การขยายลักษณะนี้เรียกว่า Pathname expansion สำหรับความหมายของ ?, *, และ character class, [...] กล่าวถึงไว้ในสัปดาห์ที่แล้ว จึงไม่กล่าวซ้ำอีก Tilde expansion, ~ ------------------ เป็นการขยายอักขระ tilde (~) ออกเป็นชื่อเส้นทางของ home directory ของผู้ใช้ เช่น $ echo ~/readme.txt /home/staff/jira/readme.txt Brace expansion, {...} ---------------------- การขยายแบบนี้มีลักษณะที่แปลกออกไปจากแบบอื่น คือใช้สร้างสายอักขระตามรูปแบบที่กำหนดไว้ในวงเล็บปีกกา เช่น $ echo Front-{X,Y,Z}-Back # X, Y และ Z คือรูปแบบที่กำหนด Front-X-Back Front-Y-Back Front-Z-Back $ echo Number{1..6} # กำหนดรูปแบบด้วยพิสัยของตัวเลข Number1 Number2 Number3 Number4 Number5 Number6 $ echo {Z..A} # กำหนดรูปแบบด้วยพิสัยของตัวอักษร Z Y X W V U T S R Q P O N M L K J I H G F E D C B A $ echo {A..J} A B C D E F G H I J $ echo x{A{1,2},B{3,4}}y # สามารถใช้ซ้อนกันได้ xA1y xA2y xB3y xB4y การขยายแบบนี้มีที่ใช้สร้างชื่อแฟ้มหรือไดเรกทอรีที่ต้องการสร้าง ตัวอย่างเช่นการจัดไดเรกทอรีสำหรับเก็บภาพ โดยกำหนดชื่อไดเรกทอรีเป็นปีและเดือน เช่น 2018-01 หมายถึงไดเรกทอรีสำหรับเก็บภาพของเดือนมกราคม 2018 เป็นต้น หากผู้ใช้ต้องการสร้างไดเรกทอรีของทั้ง 12 เดือนในครั้งเดียว ทำได้ดังนี้ $ mkdir Photos $ cd Photos $ mkdir 2018-0{1..9} 2018-{10..12} $ ls 2018-01 2018-03 2018-05 2018-07 2018-09 2018-11 # รายชื่อไดเรกทอรีที่สร้างขึ้นใหม่ 2018-02 2018-04 2018-06 2018-08 2018-10 2018-12 และในทำนองเดียวกันรูปแบบนี้สามารถใช้ลบไดเรกทอรีเหล่านี้ได้ด้วย เช่น $ rmdir 2018-0{1..9} 2018-{10..12} Arithmetic expansion, $((...)) ------------------------------ สำหรับคำนวณค่าของนิพจน์คณิตศาสตร์ คำนวณได้เฉพาะจำนวนเต็ม มีรูปแบบทั่วไปเป็น $(( นิพจน์จำนวนเต็ม )) เช่น $ echo $((2 + 3)) 5 $ echo $((13 / 5)) 2 # 13 div 5 = 2 การหารจำนวนเต็มเพื่อเอาผลหาร $ echo $((13 % 5)) 3 # 13 mod 5 = 2 การหารจำนวนเต็มเพื่อเอาเศษ สามารถใช้ซ้อนกันได้เช่น $ echo $(($((5**)) * 3)) # ** หมายถึงยกกำลัง 75 Parameter expansion, $ชื่อตัวแปร ------------------------------ เมื่อเชลล์เริ่มทำงานจะทำการกำหนดค่า "สิ่งแวดล้อม" ในการทำงานไว้สำหรับการทำงานของเชลล์เอง และสำหรับถ่ายทอดให้โพรเซสต่างๆ นำไปใช้งาน เช่น เส้นทางการค้นแฟ้มโปรแกรม, ชื่อผู้ใช้ และ ชนิดของเทอร์มินอล เป็นต้น ค่าเหล่านี้เรียกว่า parameter ในการทำงาน โดยกำหนดไว้ในตัวแปรระบบเช่นตัวแปร PATH, USER และ TERM เป็นต้น ผู้ใช้สามารถกำหนดให้เชลล์ขยายค่าในตัวแปรเหล่านี้ได้ โดยใช้เครื่องหมาย $ นำหน้าตัวแปรนั้น เช่น $ echo $USER jira $ echo $TERM xterm-256color ในกรณีที่ผู้ใช้พิมพ์ชื่อของตัวแปรระบบผิดไป เช่น ต้องการพิมพ์ $USER แค่กลับพิมพ์เป็น $SUER เชลล์จะตีความว่าเป็นตัวแปรใหม่ที่ยังไม่ได้กำหนดค่า และจะแสดง null string เป็นค่าของตัวแปรนั้น การตรวจสอบค่าของพารามิเตอร์ (ตัวแปรระบบ) เหล่านี้ทำได้โดยใช้คำสั่ง printenv - print all or part of environment Command substitution, $(...) ---------------------------- การแทนที่คำสั่งด้วยผลลัพธ์ เป็นการกำหนดให้คำสั่งนั้นทำงาน และนำผลลัพธ์ที่ได้มาแทนที่คำสั่งนั้น เช่นหากต้องการดูรายละเอียดแฟ้มคำสั่งของตัวแปลภาษา gcc ทำได้ดังนี้ $ which gcc # หาเส้นทางไปยังโปรแกรม gcc ในระบบแฟ้มด้วยคำสั่ง which /usr/bin/gcc $ ls -l /usr/bin/gcc # นำเส้นทางที่ได้มาใช้กับคำสั่ง ls เพื่อแสดงรายละเอียด lrwxrwxrwx 1 root root 7 Apr 8 2014 /usr/bin/gcc -> gcc-4.8 เราสามารถรวมการทำงานทั้งสองขั้นตอนเข้าด้วยกันด้วยโดยใช้ command substitution ดังนี้ $ ls -l $(which gcc) lrwxrwxrwx 1 root root 7 Apr 8 2014 /usr/bin/gcc -> gcc-4.8 ผลลัพธ์ของคำสั่ง ls แสดงว่า gcc ไม่ใช่แฟ้ม และไม่ใช่ไดเรกทอรี การตรวจสอบชนิดของแฟ้มทำได้โดยใช้คำสั่ง file ดังนี้ $ file $(which gcc) /usr/bin/gcc: symbolic link to `gcc-4.8' # gcc เป็น symbolic link ไปยังแฟ้ม gcc-4.8 การทำ command substitution มีสองรูปแบบคือ $(...) ตามมาตรฐาน POSIX และการกำกับด้วยเครื่องหมาย "`", เรียกว่า backquote หรือ backtick ซึ่งเป็นรูปแบบเดิมของ Bourne shell ในปัจจุบันไม่นิยมใช้แล้ว แต่ยังคงมีไว้สำหรับให้ใช้งาน shell script รุ่นเก่าได้ -- backward compatible การควบคุมการ Expansion ของเชลล์ (Quoting) ---------------------------------------- ทำได้หลายวิธี แต่ก่อนอื่นลองดูตัวอย่างต่อไปนี้ $ echo Hello world. Hello world. ตัวอย่างนี้เชลล์จะแยกคำ กำจัดวรรคส่วนเกิน แล้วจึงส่งให้คำสั่งที่ระบุทำงาน เรียกว่า word splitting $ echo Total = $100.50 Total = 00.50 เชลล์ทำการขยาย parameter expansion โดยมองเห็น $1 เป็นตัวแปรที่ยังไม่ได้กำหนดค่า จึงแทนด้วยสายอักขระว่าง การทำ expansion ของเชลล์ในบางกรณีอาจทำให้ผลลัพธ์ผิดไปจากที่ต้องการได้ จึงต้องมีวิธียับยั้งไม่ให้เชลล์ขยายความเมื่อไม่ต้องการ วิธีการเช่นนี้เรียกว่า quoting (การกำกับ?) การกำกับด้วยอัญประกาศ (Double quotes) ------------------------------------ เมื่อกำกับข้อความด้วยเครื่องหมายคำพูด (อัญประกาศ) อักขระพิเศษทุกตัว ยกเว้น "$", "\" และ "`" จะเปลี่ยนเป็นอักขระปรกติ จึงไม่มีการทำ word splitting, pathname expansion, tilde expansion และ brace expansion แต่ยังคงมีการทำ parameter expansion, arithmetic expansion และ command substitution การทำงานของ word splitting จากตัวอย่างที่ผ่านมาคือ $ echo Hello world Hello world แสดงให้เห็นว่า word-splitting กำจัด "วรรค" ส่วนเกินในบรรทัดคำสั่ง ซึ่งการดำเนินการโดยปริยายของ word splitting คือการตรวจหา วรรค (space), ย่อหน้า (tab), และ ขึ้นบรรทัดใหม่ (newline) เพื่อใช้แยกคำ ดังนั้น วรรค, ย่อหน้า และ ขึ้นบรรทัดใหม่ จึงไม่ได้เป็นส่วนใดส่วนหนึ่งของข้อความในบรรทัดคำสั่ง เป็นแต่เพียงเครื่องหมายสำหรับแยกคำเท่านั้น บรรทัดคำสั่ง $ echo Hello world จึงประกอบด้วยคำสั่ง echo และอาร์กิวเมนต์อีกสองตัว แต่เมื่อกำกับด้วยเครื่องหมายคำพูด $ echo "Hello world" Hello world เท่ากับเป็นการยับยั้งกลไกของ word splitting วรรคที่อยู่ระหว่าง Hello และ world กลายเป็นส่วนหนึ่งของอาร์กิวเมนต์ บรรทัดคำสั่งจึงประกอบด้วยคำสั่ง echo และอาร์กิวเมนต์หนึ่งตัวคือ "Hello world" นอกจากข้อความธรรมดาแล้ว ยังมีผลต่อชื่อแฟ้มด้วย เช่น พิมพ์ชื่อแฟ้มผิดโดยมีวรรคอยู่ในชื่อแฟ้ม $ touch two words.txt # touch ใช้สร้างแฟ้มเปล่า หรือเปลี่ยนแปลงข้อมูลวันเวลา (timestamp) ของแฟ้ม $ ls -l -rw------- 1 jira staff 0 Jan 21 15:14 two -rw------- 1 jira staff 0 Jan 21 15:14 words.txt ผลที่ได้คือได้แฟ้มเปล่าสองแฟ้มคือ two และ words.txt เพราะเชลล์แยก two words.txt ออกเป็นสองคำ คือ two และ words.txt ก่อนส่งให้คำสั่ง touch ดำเนินการ จึงได้แฟ้มสองแฟ้ม (หรือเรียกว่าเชลล์ทำ word splitting) เมื่อลบแฟ้มทั้งสองออก และทำการสร้างใหม่โดยการกำกับด้วยเครื่องหมายคำพูด $ touch "two words.txt" # ยับยั้งการทำ word splitting ได้ $ ls -l -rw------- 1 jira staff 0 Jan 21 15:11 two words.txt การกำกับด้วยเครื่องหมายคำพูด ไม่สามารถยับยั้งการดำเนินการต่อไปนี้ได้ $ echo "$USER" # ไม่สามารถยับยั้งการทำ parameter expansion ได้ jira $ echo "Total = $100.50" Total = 00.50 $ echo "$((2 * 6))" # ไม่สามารถยับยั้งการทำ arithmetic expansion ได้ 12 $ echo "$(which gcc)" # ไม่สามารถยับยั้งการทำ command substitution ได้ /usr/bin/gcc ประเด็นที่น่าสนใจอีกอย่างหนึ่งจากการที่เชลล์ถือว่า newline เป็นเครื่องหมายแยกคำด้วย ทำให้เกิดผลที่อาจดูแปลกและยากต่อการทำความเข้าใจ เมือเกิดในผลลัพธ์ที่ได้จากการทำ command substitution เช่น $ cal # คำสั่ง cal ใช้สำหรับแสดงปฏิทินของเดือนปัจจุบัน January 2018 # cal -m <หมายเลขเดือน> แสดงปฏิทินของเดือนนั้น ในปีปัจจุบัน Su Mo Tu We Th Fr Sa # cal -3 แสดงปฏิทินของเดือนปัจจุบัน เดือนก่อนหน้า และเดือนที่ตามมา 1 2 3 4 5 6 # cal [-y] ปี ค.ศ. แสดงปฏิทินของปีนั้น 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 เมื่อทำ command substitution เชลล์จะกำจัด newline ซึ่งเป็นเครื่องหมายแยกคำออกจากผลลัพธ์ด้วย ดังนี้ $ echo $(cal) January 2018 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 หากต้องการรักษาวรรค และ newline ไว้ ต้องกำกับการทำ command substitution ในเครื่องคำพูด $ echo "$(cal)" January 2018 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 การกำกับด้วย Single quote ----------------------- ในกรณีที่ "ไม่ต้องการ" ให้เชลล์ทำการขยายเลย ทำได้โดยการกำกับด้วยเครื่องหมายคำพูดเดี่ยว หรือ single quote เช่น $ echo '$USER' $USER $ echo 'Total = $100.50' Total = $100.50 $ echo '$((2 * 6))' $((2 * 6)) $ echo '$(which gcc)' $(which gcc) Escape character ---------------- ในกรณีที่ต้องการกำกับการขยายผลของอักขระพิเศษเพียงตัวเดียว ทำได้โดยการใส่เครื่องหมาย backslash (\) หน้าอักขระนั้น มีผลทำให้อักขระนั้นเป็น escape character โดยทั่วไปใช้กำกับอักขระเฉพาะตัวของข้อความที่กำกับด้วยเครื่องหมายคำพูด เช่น $ echo "Total = \$100.50" Total = 100.50 ในกรณีที่ต้องการใช้ \ ในข้อความ ทำได้โดยการใช้ \\ การกำกับอักขระพิเศษด้วย \ อาจนำไปใช้ในการแทรกอักขระพิเศษลงในชื่อแฟ้ม เช่น "$", "!", "&", และ " " เป็นต้น สำหรับแฟ้มสำคัญเพื่อป้องกันการลบโดยไม่ได้ตั้งใจ เรียบเรียงจาก ---------- Expansion - http://linuxcommand.org/lc3_lts0080.php (มกราคม ๒๕๖๑) ------------------------------------------------------------ ตอนที่ ๒ การกำหนดสิทธิการใช้งานแฟ้ม setuid, setgid และ sticky bit -------------------------------------------------------------- นอกจากสิทธิการใช้งานแฟ้มและไดเรกทอรีแบบ read, write และ execute แล้ว ยังมีสิทธิการใช้งานแฟ้มอีกชุดหนึ่งคือ setuid, setgid และ sticky bit สำหรับกำหนดให้แฟ้มและไดเรกทอรีเพิ่มเติม และก่อนที่จะอธิบายรายละเอียดขอทบทวนเรื่องของผู้ใช้ (user) และกลุ่ม (group) ก่อนดังนี้ ผู้ใช้ (user) ---------- ผู้ใช้แต่ละคนมีขื่อผู้ใช้ (user name หรือ login name) และหมายเลขผู้ใช้เรียกว่า user identification number (UID) สำหรับตรวจสอบการเข้าใช้งาน และตรวจสอบความเป็นเจ้าของแฟ้มและไดเรกทอรี ผู้ใช้มีสองประเภท - superuser ทำหน้าที่สร้างผู้ใช้, กลุ่ม, และดูแลบริหารจัดการระบบ มีสิทธิในการใช้งานระบบสูงสุด มีชื่อผู้ใช้เป็น root และมีหมายเลขผู้ใช้เป็น 0 - ผู้ใช้ทั่วไป มีสิทธิการใช้งานตามที่ผู้ดูและบบกำหนด โดยทั่วไปการเข้าใช้งานระบบ ผู้ใช้ต้องป้อนชื่อและรหัสผ่านให้ถูกต้อง ข้อมูลพื้นฐานของผู้ใช้เก็บในแฟ้ม /etc/passwd ส่วนรหัสผ่านจะทำการเข้ารหัสเก็บในแฟ้ม /etc/shadow รวมทั้งข้อจำกัดต่างๆ สำหรับผู้ใช้นั้นด้วย กลุ่ม (group) ----------- group หรือกลุ่ม ผู้ใช้ที่อยู่ในกลุ่มเดียวกัน สามารถใช้แฟ้มและทรัพยากรอื่นในระบบร่วมกัน เช่น ผู้ใช้ที่อยู่ในโครงการเดียวกันควรจัดเป็นกลุ่มเดียวกัน กลุ่มแต่ละกลุ่ม ประกอบด้วยชื่อกลุ่ม และหมายเลขกลุ่มสำหรับอ้างอิง เรียกว่า group identification number (GID) กลุ่มมีสองแบบคือ - Primary group เป็นกลุ่มที่ผู้ดูแลระบบกำหนดให้ เมื่อมีการสร้างผู้ใช้ ผู้ใช้แต่ละคนมีกลุ่มหลักได้เพียงกลุ่มเดียว - Secondary group เป็นกลุ่มที่ผู้ใช้สามารถสังกัดได้ โดยทั่วไปมีจำนวนสูงสุดไม่เกิน 15 กลุ่ม เมื่อผู้ใช้สร้างแฟ้มและไดเรกทอรี สิทธิการใช้งานของกลุ่มจะเป็นไปตามกลุ่มหลักเสมอ สำหรับกลุ่มรองมีไว้ให้ผู้ใช้สามารถใช้โปรแกรมและแฟ้มที่เป็นของกลุ่มที่สังกัดอยู่ได้ นอกจากสิทธิ read, write และ execute สำหรับผู้ใช้ (user), กลุ่ม (group) และผู้อื่น (other) ของแฟ้มและไดเรกทอรีแล้ว ยังมีสิทธิพิเศษอีกชุดหนึ่งคือ setuid, setgid และ sticky bit ใช้กำหนดให้กับแฟ้มและไดเรกทอรีเพื่อให้มีคุณสมบัติตามต้องการ มีชื่ออีกอย่างหนึ่งว่า Unix access rights flags SUID (set user identification) ----------------------------- ใช้กำหนดให้กับ "แฟ้มโปรแกรม" เพื่อให้โปรแกรมนั้นมีสิทธิในการทำงานเทียบเท่าเจ้าของแฟ้มโปรแกรม ถึงแม้ผู้ใช้อื่นจะเป็นผู้เรียกให้ทำงาน ซึ่งโดยปกติเมื่อมีการใช้งานโปรแกรม สิทธิการทำงานของโปรแกรมนั้นเป็นไปตามสิทธิของผู้เรียกใช้งาน กำหนดด้วยอักษร S หรือ s ในตำแหน่ง x ของเจ้าของ SGID (set group identification) ------------------------------- ใช้กำหนดให้กับ "ไดเรกทอรี" เพื่อให้แฟ้มที่สร้างขึ้นในไดเรกทอรีนั้นมี "กลุ่ม" เป็นไปตามกลุ่มของเจ้าของไดเรกทอรีนั้น กำหนดด้วยอักษร S หรือ s ในตำแหน่ง x ของกลุ่ม Sticky bit ---------- ใช้กำหนดให้กับ "ไดเรกทอรี" เพื่อทำให้แฟ้มที่อยู่ในไดเรกทอรีนั้นถูกลบได้เฉพาะจากเจ้าของแฟ้ม, เจ้าของไดเรกทอรี หรือโดย root ผู้ใช้อื่นไม่มีสิทธิในการลบ (ถึงแม้ว่าจะมีสิทธิ w ในไดเรกทอรีนั้น) ใช้ในไดเรกทอรีที่ผู้ใช้หลายคนใช้งานร่วมกัน กำหนดด้วยอักษร T หรือ t ในตำแหน่ง x ของผู้ใช้อื่น สรุปรวมสัญลักษณ์และความหมายของ setuid, setgid และ sticky bit ได้ดังนี้ ----------- ------------------------------------------------ สิทธิ ความหมาย ----------- ------------------------------------------------ --S --- --- กำหนดสิทธิ SUID แต่ไม่ได้กำหนดสิทธิ x ของเจ้าของ --s --- --- กำหนดสิทธิ SUID และกำหนดสิทธิ x ของเจ้าของ --- --S --- กำหนดสิทธิ SGID แต่ไม่ได้กำหนดสิทธิ x ของกลุ่ม --- --s --- กำหนดสิทธิ SGID และกำหนดสิทธิ x ของกลุ่ม --- --- --T กำหนด Sticky bit แต่ไม่ได้กำหนดสิทธิ x ของผู้ใช้อื่น --- --- --t กำหนด Sticky bit และกำหนดสิทธิ x ของผู้ใช้อื่น ----------- ------------------------------------------------ ตัวอย่างการใช้งาน -------------- คำอธิบาย setuid, setgid และ sticky bit อาจไม่ช่วยให้ผู้อ่านเข้าใจได้ชัดเจนนัก ตัวอย่างต่อไปนี้อาจช่วยเสริมความเข้าใจให้ชัดเจนขึ้น ตัวอย่างการใช้งาน SUID: คำสั่ง passwd สำหรับเปลี่ยนรหัสผ่าน -------------------------------------------------------- เมื่อผู้ใช้เรียกใช้คำสั่ง passwd เพื่อเปลี่ยนรหัสผ่าน แฟ้มคำสั่งนี้มี root เป็นเจ้าของ และคำสั่งนี้ยังต้องแก้ไขข้อมูลในแฟ้ม /etc/passwd, /etc/shadow, และอาจมีแฟ้มอื่นๆ อีกด้วย แฟ้มเหล่านี้มี root เป็นเจ้าของ ผู้ใช้อื่นมีสิทธิเฉพาะอ่านเท่านั้น เช่น $ ls -l /etc/passwd -rw-r--r-- 1 root root 168709 Apr 24 2017 /etc/passwd เพื่อให้ผู้ใช้ที่เรียกใช้คำสั่ง passwd สามารถแก้ไขข้อมูลในแฟ้ม /etc/passwd ได้เมื่อเรียกใช้คำสั่ง passwd จึงต้อง set ค่า setuid ดังนี้ $ ls -l $(which passwd) -rwsr-xr-x 1 root root 47032 May 17 2017 /usr/bin/passwd # setuid และ execute ตัวอย่างการใช้งาน SGID ------------------ ตัวอย่างการใช้งาน SGID อาจไม่ชัดเจนนัก เพราะเป็นการกำหนดตามลักษณะงานที่ทำ โดยทั่วไปมีการใช้งานเมื่อมีผู้ใช้ที่สังกัดกลุ่มหลายกลุ่มที่ได้รับมอบหมายให้ทำงานในหลายโครงการ เช่นผู้ใช้ bb สังกัดกลุ่มสองกลุ่มคือ XX และ YY ได้รับมอบหมายให้ทำงานในโครงการ robot ซึ่งมี aa ซึ่งสังกัดกลุ่ม YY เป็นหัวหน้าโครงการ เมื่อเริ่มงาน aa สร้างไดเรกทอรี robodir ขึ้น เพื่อใช้เป็นไดเรกทอรีเก็บโปรแกรมและเอกสารร่วมกันสำหรับสมาชิกในโครงการ และกำหนดให้ไดเรกทอรีนี้มีสิทธิเป็น drwxrws--- เมื่อ bb สร้างแฟ้มใหม่ในไดเรกทอรีนี้ จะทำให้แฟ้มนี้อยู่ในกลุ่ม YY (แทนที่จะเป็น XX ซึ่งเป็นกลุ่มหลักของ bb) ทำให้สมาชิกทึกคนในกลุ่ม YY ใช้งานแฟ้มนี้ ตัวอย่างการใช้งาน Sticky bit: ไดเรกทอรี /tmp ---------------------------------------- ไดเรกทอรี /tmp เป็นไดเรกทอรีที่ระบบกำหนดไว้สำหรับให้โปรแกรมต่างๆ สร้างแฟ้มใช้งานชั่วคราว (tempory file) ระหว่างการทำงาน และลบทิ้งไปเมื่อเลิกทำงาน จึงต้องกำหนดให้มีสิทธิการทำงานทุกอบ่างสำหรับเจ้าของ กลุ่ม และผู้ใช้อื่น หรือมีสิทธิเป็น drwxrwxrwx ซึ่งมีผลให้ผู้ใช้สามารถอ่าน แก้ไข และลบแฟ้มของผู้ใช้อื่นได้ จึงต้องกำหนด sticky bit เพื่อจำกัดให้ผู้ใช้แต่ละคนมีสิทธิใช้งานงานเฉพาะแฟ้มของตนเท่านั้น ดังนี้ $ ls -ld /tmp drwxrwxrwt 11 root root 20480 Jan 24 08:11 tmp หากทำการลบแฟ้มของผู้ใช้อื่น จะปรากฏผลดังตัวอย่าง -rw------- 1 lecturer teacher 0 Jan 23 06:56 zfile $ rm zfile rm: remove write-protected regular file âzfileâ? y # จะลบแฟ้มที่มีการป้องกันการเขียนหรือ? yes rm: cannot remove âzfileâ: Operation not permitted # ไม่สามารถลบได้ ไม่ได้รับอนุญาตให้ดำเนินการ คำถาม: เพราะเหคุใดระบบจึงเตือนว่า "จะลบแฟ้มที่มีการป้องกันการเขียนหรือ?" (คำแนะนำ - สิทธิของแฟ้มและสิทธิของไดเรกทอรี) คำเตือน: สิทธิการใช้งาน setuid ใช้กับแฟ้มโปรแกรม ส่วน setgid sticky bit ใช้กับไดเรกทอรี การใช้งานนอกเหนือจากนี้ขึ้นอบู่กับระบบแต่ละระบบ หากสนใจอ่านคู่มือของระบบนั้นๆ ให้เข้าใจชัดเจนก่อนลงมือดำเนินการ การกำหนดและการถอนสิทธิ setuid, setgid และ sticky bit ----------------------------------------------------- การกำหนดสิทธิ ทำได้โดยใช้คำสั่ง chmod โดยมีลำดับของบิตเป็น setuid, setgid และ stick bit ตามลำดับ ตัวอย่างการกำหนด setuid ให้กับไดเรกทอรี mydir ที่มีสิทธิการใช้งานดังนี้ $ ls -l drwxrwx--- 2 jira staff 4096 Jan 24 11:05 mydir ต้องการเพิ่มสิทธิ sgid สำหรับไดเรกทอรี mydir ใช้คำสั่งดังนี้ $ chmod 2770 mydir # หรือ chmod 02770 $ ls -l drwxrws--- 2 jira staff 4096 Jan 24 11:05 mydir หากต้องการถอน (clear) ทำได้โดยใช้คำสั่ง chmod เช่นเดียวกัน แต่ "ต้อง" เพิ่มศูนย์ (0) เข้าข้างหน้าอีกหลักหนึ่ง มิฉะนั้นจไม่เกิดผลใด $ chmod 0770 mydir $ ls -l drwxrws--- 2 jira staff 4096 Jan 24 11:05 mydir setuid ยังคงเดิมไม่เปลี่ยนแปลง ต้องเพิ่ม 0 นำหน้าจึงจะได้ผล $ chmod 00770 mydir # นำหน้าด้วย 0 $ ls -l drwxrwx--- 2 jira staff 4096 Jan 24 11:05 mydir ข้อสังเกตที่น่าสนใจอีกอย่างหนึ่งคือ ตอนกำหนด setuid และ setgid ด้วยเลขฐานแปด จะนำหน้าด้วยศูนย์หรือไม่ก็ได้ แต่ตอนถอนสิทธิจำเป็นต้องใช้ แนวปฏิบัติที่ดีอย่างหนึ่งคือ ไม่ว่าจะเป็นการกำหนดหรือการถอนสิทธิ เพิ่มศูนย์นำหน้าให้เป็นเลขฐานแปด 5 หลักเสมอ ------------------------------------------------------------ ตอนที่ ๓ ความแตกต่างระหว่าง text file และ binary file -------------------------------------------------- คำสั่ง cat (concatenation) ใช้สำหรับแสดงผลข้อมูลในแฟ้มชนิด Text file ออกทางจอภาพ คำถามที่ได้ยินในห้องปฏิบัติการคือ text file คืออะไร? แฟ้มในระบบคอมพิวเตอร์สามารถแบ่งได้เป็น 2 ชนิด คือ binary file และ text file แฟ้มทั้งสองประเภทนี้มีลักษณะภายนอกเหมือนกัน, "ข้อมูล" ภายในแฟ้มก็เป็น stream of bits เช่นเดียวกัน เพียงแต่บิตข้อมูลใน text file เป็นรหัสแทนอักขระ ส่วนข้อมูลใน binary file เป็น รหัสแทนข้อมูลที่มีการกำหนดขึ้นเอง และมีความหมายแตกต่างกันออกไปตามชนิดของ Application หากพิจารณาในลักษณะนี้ จะเห็นว่า text file เป็นเซตย่อยของ binary file ด้วยเหตุนี้ฟังก์ชันในภาษา C หรือ System call ใดๆ ของ Unix ที่สามารถใช้งานกับ binary file จึงสามารถใช้งานกับ text file ได้ด้วย หรือกล่าวอีกนัยหนึ่งคือ text file เป็นกรณีพิเศษของ binary file ซึ่งมีเฉพาะรหัสแทนอักขระที่สามารถพิมพฺ์ให้ปรากฎตัวอักขระนั้นบนจอภาพได้ เรียกว่า printable characters สำหรับรหัส ascii ภาษาอังกฤษ ได้แก่ รหัส ascii ตั้งแต่ 32 (ฐานสิบ) ขึ้นไป ส่วนรหัส ascii ที่อยู่ในช่วง 0 - 31 เรียกว่ารหัสควบคุม (Control characters) ซึ่งใช้ในการควบคุม อุปกรณ์ต่างๆ เช่นคุมการแสดงอักขระบนจอภาพ, การสื่อสารข้อมูล, และใช้เป็นเครื่องหมายสำหรับการแยกข้อมูล เป็นต้น แฟ้มชนิด text file คือแฟ้มที่ข้อมูลภายในมีเฉพาะ printable characters และรหัสควบคุมที่ใช้ในการแสดงอักขระบนจอภาพ ซึ่งได้แก่ รหัส ascii ในช่วง 8 - 13 รวม 6 ตัว ตามลำดับดังนี้คือ backspace, horizontal tab, new line, vertical tab, form feed, และ carriage return Text file เป็นแฟ้มที่ได้จากโปรแกรม editor เช่น vi, emacs, notepad, codeblock และ edtor ที่รวมเบ็ดเสร็จอยู่ในตัวแปลภาษาต่างๆ เช่นแฟ้มโปรแกรมต้นฉบับ และ เอกสาร HTML และ XML เป็นต้น เมื่อนิยามแฟ้มชนิด text file ได้แล้ว จึงนิยาม binary file ให้เป็นนิเสธของ text file คือ แฟ้มที่ไม่ใช่ text file คือแฟ้มชนิด binary file หรือหากเขียนตามแบบภาษา C จะได้เป็น #define binary_file !(text_file) ------------------------------------------------------------