← สารบัญบทเรียน M11 · Software & Time
M11 · หัวข้อสอบ

ติดตั้งซอฟต์แวร์ & ตั้งเวลา

บนเซิร์ฟเวอร์จริง เราไม่โหลดโปรแกรมจากเว็บมั่วๆ มาลง — เราใช้ “ระบบ package” ที่จัดการให้ครบและปลอดภัย บทนี้สอนตั้งแต่ลง/ลบ/อัปเดตโปรแกรมด้วย dnf ไปจนถึงตั้งเวลาและซิงค์นาฬิกาให้ตรงเป๊ะด้วย NTP

🌱 บทนี้เขียนเพื่อคนที่ไม่เคยแตะ Linux มาก่อนเลย

1ลงโปรแกรมบน Linux ไม่เหมือน Windows ตรงไหน

ถ้าคุณคุ้นกับ Windows การลงโปรแกรมคือ — เปิดเว็บ โหลดไฟล์ .exe มา ดับเบิลคลิก กด Next Next Next จบ แต่บน RHEL เราไม่ทำแบบนั้น เพราะมันไม่ปลอดภัยและจัดการยาก ลองคิดดูว่าถ้าเซิร์ฟเวอร์มี 100 เครื่อง คุณจะไล่โหลดไฟล์ทีละเครื่องไหวไหม

แทนที่จะทำแบบนั้น Linux มี ระบบ package — เป็นคลังซอฟต์แวร์กลางที่ผ่านการตรวจสอบแล้ว เราแค่บอกชื่อโปรแกรมที่อยากได้ ระบบก็จะไปดึงมาลงให้พร้อม “ของที่จำเป็น” ครบเซ็ต

💡 เปรียบเทียบให้เห็นภาพ

การโหลด .exe จากเว็บมั่วๆ = ไปซื้อของกินจากแผงข้างทางที่ไม่รู้สะอาดไหม

ระบบ package ของ Linux = สั่งของจาก App Store ที่คัดกรองแล้ว มีลายเซ็นรับรองของแท้ และถ้าแอปต้องใช้แอปอื่นช่วย มันจะลงให้ครบเองโดยไม่ต้องไปตามหา

🎯 ทำไมข้อนี้ออกสอบ

RHCSA ชอบให้ “ลง package ตัวนี้”, “ลบตัวนั้น”, “เพิ่ม repo จาก URL ที่กำหนด”, หรือ “ตั้ง timezone ให้ถูก” — ทั้งหมดต้องทำด้วยคำสั่งให้คล่อง และต้องเขียนถาวรให้รอดหลังรีบูตด้วย

2RPM กับ DNF — package คืออะไร

มีสองคำที่ต้องแยกให้ออก เพราะคนมักสับสน:

RPM
ตัว “กล่องซอฟต์แวร์” — ไฟล์นามสกุล .rpm หนึ่งกล่องคือหนึ่งโปรแกรม (เช่น nginx) ข้างในมีไฟล์โปรแกรม + ข้อมูลว่าต้องพึ่งกล่องอื่นไหม
DNF
“ผู้จัดการที่ฉลาด” — เครื่องมือที่ไปดึงกล่อง .rpm จากคลัง (repository) มาลงให้ และที่เก่งคือมันจัดการ dependency (ของที่จำเป็นต้องมี) ให้เองครบ
💡 เปรียบเทียบให้เห็นภาพ

ถ้าคุณติดตั้ง .rpm ด้วยมือเปล่า (คำสั่ง rpm -i) มันเหมือน ซื้อชั้นวางหนังสือ IKEA แต่ลืมซื้อน็อต — ประกอบไม่ได้ ต้องวิ่งไปหาน็อตเอง

แต่ถ้าใช้ dnf มันเหมือนสั่งจากร้านที่ แถมน็อต ไขควง และคู่มือมาให้ครบในกล่องเดียว — สั่งโปรแกรมเดียว มันลง dependency ให้หมดอัตโนมัติ

📌 สมัยก่อนชื่อ yum

คุณอาจเคยเห็นคำสั่ง yum ในคู่มือเก่าๆ — บน RHEL 9 มันคือ dnf ตัวเดียวกัน (yum ยังพิมพ์ได้อยู่ มันชี้ไปที่ dnf ให้) ในห้องสอบจะใช้ตัวไหนก็ได้ แต่แนะนำให้ชินกับ dnf

3คำสั่ง dnf ที่ต้องใช้เป็น

คำสั่งที่เปลี่ยนแปลงระบบ (ลง/ลบ/อัปเดต) ต้องใช้สิทธิ์ root ดังนั้นเติม sudo นำหน้า ส่วนคำสั่งแค่ “ดู” (search/info/list) ใช้ user ธรรมดาก็ได้

install — ลงโปรแกรม

⌨️ ลองดู
[student@server1 ~]$ sudo dnf install httpd
Dependencies resolved.
================================================================
 Package          Arch     Version        Repository      Size
================================================================
Installing:
 httpd            x86_64   2.4.57-5.el9   appstream       1.5 M
Installing dependencies:
 apr              x86_64   1.7.0-12.el9   appstream       127 k
 apr-util         x86_64   1.6.1-23.el9   appstream        98 k
...
Is this ok [y/N]: y
Complete!

สังเกตว่าเราสั่งลงแค่ httpd แต่ dnf เห็นว่ามันต้องใช้ apr, apr-util ด้วย เลย ลงให้ครบเอง นี่แหละความฉลาดของ dnf

-yเติมท้ายเพื่อตอบ “yes” อัตโนมัติ ไม่ต้องมานั่งกด y เอง เช่น dnf install -y httpd

คำสั่งหลักทั้งหมด

⌨️ ชุดคำสั่ง dnf ที่ใช้บ่อยที่สุด
$ sudo dnf install ชื่อ     # ลงโปรแกรม (+ dependency)
$ sudo dnf remove ชื่อ      # ลบโปรแกรมออก
$ sudo dnf upgrade          # อัปเดตทุกอย่างให้ใหม่ล่าสุด (= update)
$ dnf search คำ            # ค้นหา package จากคำ
$ dnf info ชื่อ             # ดูรายละเอียด: เวอร์ชัน ขนาด คำอธิบาย
$ dnf list installed       # ลิสต์ทุก package ที่ลงแล้ว
$ dnf provides /usr/sbin/httpd  # ไฟล์นี้มาจาก package ไหน?
$ dnf history               # ดูประวัติว่าเคยลง/ลบอะไรไปบ้าง
installลงโปรแกรมใหม่ ลง dependency ให้ครบ
removeลบออก (ระวัง: อาจลบ dependency ที่ของอื่นใช้ร่วมตามไปด้วย)
upgradeอัปเดตให้เป็นเวอร์ชันล่าสุด — update ก็ความหมายเดียวกัน
searchนึกชื่อไม่ออก ลองค้นจากคำใกล้เคียง เช่น dnf search web server
infoอยากรู้ว่า package นี้คืออะไร เวอร์ชันไหน ก่อนตัดสินใจลง
providesเจอไฟล์แปลกๆ อยากรู้ว่ามันมาจากโปรแกรมไหน ใช้ตัวนี้
historyดูบันทึกย้อนหลัง และยัง dnf history undo เลขที่ เพื่อย้อนกลับได้
💡 search กับ provides ต่างกัน

dnf search = ค้นจาก ชื่อ/คำอธิบาย ของ package (เช่นหาคำว่า "editor")
dnf provides = ค้นจาก ชื่อไฟล์หรือ path ว่ามาจาก package ไหน (เช่น /etc/httpd มาจากตัวไหน)

4กลุ่ม package (Group)

บางทีเราอยากได้ “ชุดเครื่องมือ” ทั้งชุด ไม่ใช่ทีละตัว เช่นอยากได้เครื่องมือพัฒนาโปรแกรมครบเซ็ต RHEL จึงรวม package หลายตัวไว้เป็น กลุ่ม (group) สั่งทีเดียวได้ทั้งกลุ่ม

💡 เปรียบเทียบ

package เดี่ยว = สั่งกาแฟแก้วเดียว / group = สั่ง “เซ็ตอาหารเช้า” ที่มาพร้อมกาแฟ ขนมปัง ไข่ ครบจานเดียว

⌨️ ลองดู
$ dnf group list
Available Groups:
   Development Tools
   System Tools
   Container Management

$ sudo dnf group install "Development Tools"
Complete!
group listดูว่ามีกลุ่มอะไรให้เลือกบ้าง
group install "ชื่อ"ลงทั้งกลุ่ม — ชื่อกลุ่มมีช่องว่าง ต้องครอบด้วยเครื่องหมายคำพูด

5Module Streams — เลือกเวอร์ชันซอฟต์แวร์

นี่เป็นของใหม่ของ RHEL 9 (มาจากระบบ AppStream) และ ออกสอบบ่อย — ปัญหาคือบางโปรแกรมมีหลายเวอร์ชันให้เลือก เช่น PHP มีทั้ง 8.1 และ 8.2 แต่บนเครื่องเดียวจะลงพร้อมกันไม่ได้ Module stream คือวิธีให้เรา เลือกว่าจะเอาเวอร์ชันไหน

💡 เปรียบเทียบ

นึกถึง Netflix ที่มีหนังเรื่องเดียวกันหลาย “ซีซัน” — module = ชื่อหนัง (เช่น php), stream = ซีซัน/เวอร์ชัน (เช่น 8.2) คุณเลือกได้ว่าจะดูซีซันไหน แต่เปิดดูได้ทีละซีซัน

⌨️ ลองดู
$ dnf module list php
Name    Stream      Profiles            Summary
php     8.1 [d]     common [d], devel   PHP scripting language
php     8.2         common, devel       PHP scripting language
  [d] = default   [e] = enabled   [i] = installed

$ sudo dnf module install php:8.2
Complete!
module listดูว่ามี module อะไร และแต่ละตัวมี stream (เวอร์ชัน) อะไรบ้าง
module install php:8.2เลือก stream 8.2 แล้วลงเลย — รูปแบบคือ ชื่อ:stream
module enable php:8.2แค่เลือกเวอร์ชัน แต่ยังไม่ลง (เตรียมไว้ให้ลงทีหลัง)
module reset phpรีเซ็ตให้ลืมการเลือกทั้งหมด กลับไปเริ่มใหม่
😅 enable ≠ install — จุดที่คนพลาดกันเยอะ

module enable แค่ “เปิด” ให้เวอร์ชันนั้นพร้อมเลือก แต่ยังไม่ติดตั้ง ถ้าโจทย์บอกให้ “ติดตั้ง php เวอร์ชัน 8.2” ต้องใช้ module install php:8.2 ไม่ใช่ enable เฉยๆ (หรือ enable ก่อนแล้วค่อย dnf install php ก็ได้)

💡 ถ้าเลือก stream ผิด

เผลอ enable เวอร์ชันผิดไปแล้ว แก้ด้วย sudo dnf module reset ชื่อ เพื่อล้างค่า แล้วค่อยเลือกใหม่ ไม่ต้องตกใจ

6rpm — สืบประวัติ package

dnf ไว้ “ลง/ลบ” แต่ rpm เก่งเรื่อง “สืบ/ค้น” ว่าตอนนี้บนเครื่องมีอะไรลงอยู่บ้าง option ที่ใช้คู่กับ -q (query = ถามข้อมูล) จำ 3 ตัวนี้พอ

⌨️ ลองดู
$ rpm -qa
bash-5.1.8-6.el9.x86_64
httpd-2.4.57-5.el9.x86_64
... (ลิสต์ยาวมาก — มักใช้คู่กับ grep)

$ rpm -qf /usr/sbin/httpd
httpd-2.4.57-5.el9.x86_64

$ rpm -ql httpd
/etc/httpd
/usr/sbin/httpd
/var/www/html
...
rpm -qaa = all → ลิสต์ทุก package ที่ลงแล้ว (มักทำ rpm -qa | grep httpd)
rpm -qf pathf = file → ไฟล์นี้มาจาก package ไหน (เหมือน dnf provides แต่ดูเฉพาะที่ลงแล้ว)
rpm -ql ชื่อl = list → package นี้วางไฟล์ไว้ที่ไหนบ้าง
📌 จำง่ายๆ: dnf ลงของ / rpm ดูของ

เวลาจะ เปลี่ยน ระบบ (ลง/ลบ/อัปเดต) → ใช้ dnf เพราะจัดการ dependency ให้ เวลาจะแค่ ดู/ค้น ว่ามีอะไรลงอยู่ → ใช้ rpm -q ได้เลย

7เพิ่ม Repository เอง

Repository (repo) คือ “คลังซอฟต์แวร์” ที่ dnf ไปหยิบของมาลง บางครั้งของที่เราต้องการไม่ได้อยู่ในคลังมาตรฐาน เราจึงต้อง บอก dnf ว่ามีคลังเพิ่มอยู่ตรงไหน — ข้อนี้ออกสอบบ่อย โจทย์มักให้ URL/BaseURL มา แล้วให้เราเพิ่มเข้าไป

💡 เปรียบเทียบ

repo = รายชื่อ “ร้านค้า” ที่ App Store ของเรารู้จัก ถ้าอยากได้ของจากร้านใหม่ ก็ต้องเพิ่มที่อยู่ร้านนั้นเข้าไปในรายชื่อก่อน มันถึงจะไปสั่งของจากร้านนั้นได้

วิธีที่ 1: เขียนไฟล์ .repo เอง

รายชื่อ repo ทั้งหมดเก็บเป็นไฟล์นามสกุล .repo อยู่ในโฟลเดอร์ /etc/yum.repos.d/ เราสร้างไฟล์ใหม่ใส่ข้อมูลร้านลงไป

📄 ตัวอย่างไฟล์ /etc/yum.repos.d/myrepo.repo
[myrepo]
name=My Custom Repo
baseurl=http://content.example.com/repo/
enabled=1
gpgcheck=0
[myrepo]ชื่อย่อ (ID) ของ repo อยู่ในวงเล็บเหลี่ยม ห้ามมีช่องว่าง
name=ชื่อยาวๆ ที่อ่านเข้าใจ (จะเป็นอะไรก็ได้)
baseurl=ที่อยู่ของคลัง — ตัวสำคัญที่สุด ใส่ผิดเป็นใช้ไม่ได้
enabled=1เปิดใช้งาน repo นี้ (0 = ปิดไว้)
gpgcheck=ตรวจลายเซ็นของแท้ไหม (1 = ตรวจ ต้องมี key, 0 = ไม่ตรวจ)

วิธีที่ 2: ใช้คำสั่งลัด (เร็วกว่าในห้องสอบ)

⌨️ ลองดู
$ sudo dnf config-manager --add-repo http://content.example.com/repo/
Adding repo from: http://content.example.com/repo/

$ dnf repolist
repo id        repo name
myrepo         My Custom Repo
config-manager --add-repo URLสร้างไฟล์ .repo ให้อัตโนมัติจาก URL ที่ให้มา
dnf repolistเช็กว่า repo ที่เพิ่มเข้ามาแล้ว dnf มองเห็นจริงไหม
🎯 เขียนถาวรแล้ว แต่ต้องตรวจให้ถูก

ไฟล์ .repo เก็บอยู่ในดิสก์ รอดหลังรีบูตอยู่แล้ว ไม่ต้องทำอะไรเพิ่ม แต่ต้องเช็กสองอย่างให้ดี: (1) baseurl ถูกต้องไหม ลองด้วย dnf repolist หรือ dnf install package-ในนั้น (2) ถ้าตั้ง gpgcheck=1 ต้องมี gpgkey= ชี้ไปที่ key จริง ไม่งั้นจะลงไม่ได้

8เวลาและ Timezone: timedatectl

มาถึงครึ่งหลังของบท — เรื่อง เวลา ฟังดูเล็กน้อย แต่สำคัญมากบนเซิร์ฟเวอร์ ถ้านาฬิกาเครื่องเพี้ยน log จะจดเวลาผิด, ใบรับรอง (certificate) อาจใช้ไม่ได้, และระบบที่คุยกันหลายเครื่องจะงงกันหมด

เครื่องมือหลักคือ timedatectl — พิมพ์เฉยๆ ก็เห็นภาพรวมทั้งหมด

⌨️ ลองดู
$ timedatectl
               Local time: Mon 2026-06-16 09:00:00 +07
           Universal time: Mon 2026-06-16 02:00:00 UTC
                Time zone: Asia/Bangkok (+07, +0700)
System clock synchronized: yes
              NTP service: active

หน้าจอนี้บอกครบ: เวลาท้องถิ่น, เวลา UTC (เวลากลางโลก), timezone ที่ตั้งไว้, และนาฬิกาซิงค์อยู่ไหม

⌨️ คำสั่งตั้งค่าเวลา
$ timedatectl list-timezones        # ดูรายชื่อ timezone ทั้งหมด
$ timedatectl list-timezones | grep Bangkok
Asia/Bangkok

$ sudo timedatectl set-timezone Asia/Bangkok   # ตั้ง timezone
$ sudo timedatectl set-time "2026-06-16 09:00:00"  # ตั้งเวลามือ
list-timezonesลิสต์ยาวมาก ใช้ | grep ช่วยหา เช่นหาคำว่า Bangkok
set-timezoneตั้งเขตเวลา ต้องพิมพ์ชื่อให้ตรงเป๊ะ เช่น Asia/Bangkok (มี / และตัวพิมพ์ใหญ่)
set-timeตั้งเวลาด้วยมือ — แต่ จะใช้ได้ต่อเมื่อปิด NTP ก่อน เพราะถ้า NTP เปิด มันจะแย่งตั้งเวลาให้เอง
🎯 timezone เขียนถาวรอัตโนมัติ

timedatectl set-timezone เปลี่ยนค่าในระบบถาวรเลย (จริงๆ มันไปแก้ลิงก์ /etc/localtime ให้) รอดหลังรีบูต ไม่ต้องตั้งซ้ำ

9ซิงค์เวลาอัตโนมัติด้วย chrony (NTP)

การตั้งเวลาด้วยมือไม่เวิร์กระยะยาว เพราะนาฬิกาเครื่องจะค่อยๆ เพี้ยน วิธีที่ถูกต้องคือให้เครื่อง ซิงค์เวลากับเซิร์ฟเวอร์เวลากลาง ผ่านระบบที่เรียกว่า NTP (Network Time Protocol) บน RHEL 9 ตัวที่ทำงานนี้คือบริการชื่อ chronyd

💡 เปรียบเทียบ

NTP เหมือน นาฬิกาบนมือถือที่ตั้งเวลาเองอัตโนมัติ — มันคอยถามเวลาจากเสาสัญญาณ/อินเทอร์เน็ตอยู่เรื่อยๆ คุณไม่ต้องมานั่งหมุนเข็มเอง chrony ก็ทำแบบเดียวกันให้เซิร์ฟเวอร์

ไฟล์ตั้งค่า: /etc/chrony.conf

ในไฟล์นี้เราระบุว่าจะไปถามเวลาจากเซิร์ฟเวอร์ตัวไหน ผ่านคำว่า server หรือ pool

📄 บางส่วนใน /etc/chrony.conf
pool 2.rhel.pool.ntp.org iburst
server time.example.com iburst
driftfile /var/lib/chrony/drift
serverระบุเซิร์ฟเวอร์เวลา 1 ตัว (โจทย์มักให้ชื่อ server มาเติมตรงนี้)
poolระบุ “กลุ่ม” เซิร์ฟเวอร์เวลาหลายตัว เผื่อบางตัวล่ม
iburstให้ซิงค์เร็วขึ้นตอนเริ่มต้น (ใส่ต่อท้ายตามปกติ)

หลังแก้ไฟล์ ต้องรีสตาร์ทบริการ

⌨️ ลองดู
$ sudo systemctl restart chronyd     # โหลดค่าใหม่จากไฟล์
$ sudo timedatectl set-ntp true        # เปิดการซิงค์เวลาอัตโนมัติ

$ chronyc sources
MS Name/IP address     Stratum Poll Reach LastRx Last sample
===========================================================
^* time.example.com          2    6   377    21   +12us
systemctl restart chronydสำคัญมาก: แก้ไฟล์ chrony.conf แล้วต้อง restart มันถึงจะอ่านค่าใหม่
timedatectl set-ntp trueเปิดสวิตช์ให้ระบบซิงค์เวลาอัตโนมัติ (สั่งให้ chronyd ทำงาน)
chronyc sourcesตรวจว่ากำลังคุยกับเซิร์ฟเวอร์เวลาตัวไหน เครื่องหมาย ^* หน้าชื่อ = ตัวที่ซิงค์อยู่จริง
🎯 ตั้งค่าในไฟล์ = ถาวร แต่ต้อง enable บริการด้วย

การแก้ /etc/chrony.conf เขียนลงดิสก์ถาวรแล้ว แต่ให้แน่ใจว่าบริการรันอยู่และเปิดตอนบูตด้วย: sudo systemctl enable --now chronyd — มิฉะนั้นรีบูตแล้วเวลาอาจไม่ซิงค์

10ข้อผิดพลาดที่เจอบ่อย

11สรุปคำสั่งบทนี้ (Cheat Sheet)

คำสั่งทำอะไร
dnf install ชื่อลงโปรแกรม (พร้อม dependency)
dnf remove ชื่อลบโปรแกรม
dnf upgradeอัปเดตทุกอย่างให้ล่าสุด
dnf search คำค้น package จากคำ
dnf info ชื่อดูรายละเอียด package
dnf list installedลิสต์ package ที่ลงแล้ว
dnf provides /pathไฟล์นี้มาจาก package ไหน
dnf historyดูประวัติการลง/ลบ
dnf group install "ชื่อ"ลง package ทั้งกลุ่ม
dnf module listดู module และ stream ที่มี
dnf module install ชื่อ:streamลง module ตามเวอร์ชันที่เลือก
dnf module reset ชื่อล้างการเลือก stream
dnf config-manager --add-repo URLเพิ่ม repo จาก URL
dnf repolistดูรายชื่อ repo ที่ใช้งานอยู่
rpm -qaลิสต์ทุก package ที่ลงแล้ว
rpm -qf /pathไฟล์นี้มาจาก package ไหน
rpm -ql ชื่อpackage นี้มีไฟล์อะไรบ้าง
timedatectlดูเวลา/timezone/สถานะ NTP
timedatectl set-timezone Zตั้ง timezone (เช่น Asia/Bangkok)
timedatectl list-timezonesดูรายชื่อ timezone
timedatectl set-ntp trueเปิดซิงค์เวลาอัตโนมัติ
systemctl restart chronydรีสตาร์ทบริการเวลา (หลังแก้ conf)
chronyc sourcesดูว่าซิงค์กับ server เวลาตัวไหน
✅ จบบทนี้คุณควรทำได้

ลง/ลบ/ค้น/อัปเดต package ด้วย dnf → เลือกเวอร์ชันด้วย module stream → เพิ่ม repo จาก URL ที่โจทย์ให้ → สืบว่าไฟล์มาจาก package ไหนด้วย rpm -qf → ตั้ง timezone และเปิดซิงค์เวลา NTP ด้วย chrony ได้อย่างถูกต้องและถาวร