systemd คืออะไร ทำงานอย่างไร และจัดการบริการใน Linux อย่างไร
systemd คือระบบ init และตัวจัดการบริการของ Linux โดย kernel เรียกใช้เป็นโปรเซสแรก (PID 1) จากนั้นเปิดบริการอื่นตามลำดับที่ถูกต้องและคอยติดตาม ทุกอย่างที่ systemd ทำถูกควบคุมผ่าน unit ซึ่งเป็นคำอธิบายแบบข้อความของบริการ ไทเมอร์ จุดเมานต์ โดย systemctl ใช้สั่งเริ่ม หยุด และตั้งให้เปิดอัตโนมัติ ส่วน journalctl แสดง log
systemd คือระบบ init และตัวจัดการบริการที่ใช้ในดิสโทรสมัยใหม่ส่วนใหญ่ของ Linux เช่น Debian, Ubuntu, Fedora, RHEL และตระกูลที่สืบทอดมา หลังจากบูต kernel เรียก systemd เป็นโปรเซสแรกที่มี PID 1 จากนั้น systemd เปิดเครือข่าย เมานต์ดิสก์ เริ่มเว็บเซิร์ฟเวอร์ ฐานข้อมูล และทุกอย่างที่เหลือ กล่าวสั้นๆ systemd คือ "ตัวจัดการ" ที่รู้ว่าบริการใดควรทำงาน ควรเริ่มตามลำดับใด และควรทำอย่างไรเมื่อบริการล้มเหลว
ตรวจสอบว่าระบบของคุณใช้ systemd หรือไม่ทำได้ง่ายๆ:
$ ps -p 1 -o comm=
systemd
ทำไมจึงต้องมี systemd
ก่อนหน้านี้ Linux ใช้ SysV init ซึ่งเป็นชุดของ shell script ใน /etc/init.d/ ที่ถูกรันทีละตัว วิธีนี้เข้าใจง่ายแต่ช้าและเปราะบาง สคริปต์แต่ละตัวต้องเขียนไฟล์ PID เอง ต้องตัดสินใจเองว่าโปรเซสยังทำงานอยู่หรือไม่ และการรีสตาร์ตบริการที่ล้มเหลวต้องเขียนเพิ่มแยกต่างหาก
systemd แก้ปัญหาเหล่านี้แบบรวมศูนย์:
- การเริ่มแบบขนาน บริการที่ไม่ขึ้นต่อกันจะเริ่มพร้อมกัน ทำให้บูตเร็วขึ้น
- การพึ่งพาและลำดับ คำอธิบายบริการระบุชัดเจนว่าต้องการอะไร (เช่น เครือข่าย) และต้องเริ่มหลังอะไร
- การดูแล systemd รู้จักทุกโปรเซสของบริการผ่าน cgroups และรีสตาร์ตได้เมื่อล้มเหลว
- log รวมศูนย์ journald เก็บเอาต์พุตของทุกบริการ และดู log ได้ด้วยคำสั่งเดียว
- อินเทอร์เฟซเดียว บริการทุกตัวจัดการแบบเดียวกัน:
systemctl start|stop|restart|status
นอกจากตัวจัดการบริการ โครงการ systemd ยังมีส่วนประกอบอื่นด้วย ได้แก่ journald (log) logind (เซสชันผู้ใช้) timesyncd (ซิงก์เวลา) resolved (DNS) และ networkd (เครือข่าย) ไม่ใช่ดิสโทรทุกตัวจะใช้ครบทุกส่วน แต่ systemd ในฐานะ PID 1 และ journald แทบจะมีอยู่ทุกที่
Unit: systemd ประกอบด้วยอะไรบ้าง
ทุกสิ่งที่ systemd จัดการถูกอธิบายด้วย unit unit คือไฟล์ข้อความรูปแบบ INI ชนิดของ unit กำหนดจากนามสกุลไฟล์
| ชนิด | นามสกุล | อธิบายอะไร |
|---|---|---|
| service | .service | บริการ — โปรเซส daemon หรือ งานครั้งเดียว |
| timer | .timer | รัน unit อื่นตามกำหนดเวลา (แทน cron) |
| socket | .socket | socket ที่เมื่อมีการเชื่อมต่อจะเปิดบริการขึ้นมา |
| target | .target | กลุ่มของ unit หรือ "สถานะของระบบ" (เช่น multi-user.target) |
| mount | .mount | จุดเมานต์ |
| path | .path | เฝ้าดูไฟล์หรือไดเรกทอรี |
ไฟล์ unit อยู่ที่ไหน
ไฟล์ unit เก็บไว้หลายที่ และมีลำดับความสำคัญ:
/usr/lib/systemd/system/(บน Debian และ Ubuntu มี/lib/systemd/system/ด้วย) — unit ที่ติดตั้งมาจากแพ็กเกจ ไม่ควรแก้โดยตรง เพราะการอัปเดตแพ็กเกจจะเขียนทับ/etc/systemd/system/— unit และการแทนที่ค่าของผู้ดูแลระบบ มีลำดับความสำคัญสูงสุด/run/systemd/system/— unit ชั่วคราวที่สร้างขณะระบบทำงาน
หากต้องการดูเนื้อหาสุดท้ายของ unit พร้อมการแทนที่ทั้งหมด ใช้ systemctl cat nginx.service
Target แทน runlevel
runlevel แบบเก่าถูกแทนด้วย target multi-user.target คือโหมดเซิร์ฟเวอร์ทั่วไปที่ไม่มีกราฟิก graphical.target มีเชลล์กราฟิก rescue.target คือโหมดกู้คืนแบบผู้ใช้เดียว ดู target เริ่มต้นได้ด้วย systemctl get-default และเปลี่ยนด้วย systemctl set-default multi-user.target
systemctl: จัดการบริการ
systemctl คือเครื่องมือหลักในการทำงานกับ systemd คำสั่งส่วนใหญ่เปลี่ยนสถานะของระบบและต้องใช้ sudo
| คำสั่ง | ทำอะไร |
|---|---|
systemctl status nginx | สถานะบริการ PID หน่วยความจำ และบรรทัด log ล่าสุด |
systemctl start nginx | เริ่มทำงานทันที |
systemctl stop nginx | หยุดทำงาน |
systemctl restart nginx | เริ่มใหม่ (stop + start) |
systemctl reload nginx | โหลดการตั้งค่าใหม่โดยไม่หยุด (หากบริการรองรับ) |
systemctl enable nginx | ตั้งให้เปิดอัตโนมัติเมื่อบูต |
systemctl disable nginx | ยกเลิกการเปิดอัตโนมัติ |
systemctl enable --now nginx | ตั้งให้เปิดอัตโนมัติและเริ่มทันที |
systemctl is-active nginx | แสดง active/inactive — เหมาะกับ script |
systemctl list-units --type=service | บริการที่โหลดอยู่ |
systemctl --failed | unit ที่ล้มเหลว |
systemctl daemon-reload | โหลดไฟล์ unit ใหม่หลังแก้ไข |
อ่าน systemctl status อย่างไร
$ systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: active (running) since Mon 2026-10-12 09:14:03 UTC; 2h 5min ago
Docs: man:nginx(8)
Main PID: 812 (nginx)
Tasks: 3 (limit: 2307)
Memory: 6.1M
CPU: 154ms
CGroup: /system.slice/nginx.service
├─812 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
├─813 "nginx: worker process"
└─814 "nginx: worker process"
บรรทัด Loaded บอกว่าไฟล์ unit มาจากไหน และเปิดอัตโนมัติอยู่หรือไม่ (enabled) บรรทัด Active คือสถานะปัจจุบัน: active (running) inactive (dead) หรือ failed ส่วน CGroup แสดงโปรเซสทั้งหมดของบริการ ซึ่งเป็นวิธีที่ systemd ใช้รู้ว่าโปรเซสใดเป็นของบริการ
enable ต่างจาก start อย่างไร
นี่คือจุดที่มักสับสน start เริ่มบริการทันที แต่หลังรีบูตบริการจะไม่ทำงานอีก ส่วน enable สร้าง symbolic link ในไดเรกทอรีของ target (เช่น /etc/systemd/system/multi-user.target.wants/) ทำให้บริการเริ่มตอนบูต แต่ไม่ได้เริ่มทันที จึงมักต้องทำทั้งสองอย่าง ใช้ enable --now
มีสถานะที่สามคือ mask — systemctl mask service เชื่อม unit กับ /dev/null ทำให้ไม่สามารถรันได้ทั้งด้วยมือและในฐานะ dependency เหมาะเมื่อต้องการให้บริการปิดแน่นอน
journalctl: log ของบริการ
ทุกอย่างที่บริการเขียนไปยัง stdout และ stderr จะถูก systemd-journald เก็บไว้ในไฟล์ log แบบไบนารีพร้อมข้อมูลกำกับ ได้แก่ ชื่อ unit PID ระดับความสำคัญ และเวลา อ่าน log ด้วย journalctl
journalctl -u nginx # log ของบริการเดียว
journalctl -u nginx -f # ติดตามแบบเรียลไทม์ เหมือน tail -f
journalctl -u nginx --since "1 hour ago"
journalctl -u nginx -n 50 # 50 บรรทัดล่าสุด
journalctl -b # ตั้งแต่บูตครั้งปัจจุบัน
journalctl -b -1 # การบูตครั้งก่อนหน้า
journalctl -p err -b # เฉพาะข้อผิดพลาดและที่ร้ายแรงกว่า
journalctl -k # ข้อความของ kernel
journalctl --disk-usage # log ใช้พื้นที่เท่าไร
ตัวเลือก -p กรองตามระดับความสำคัญของ syslog: emerg, alert, crit, err, warning, notice, info, debug ระดับที่ระบุจะรวมระดับที่ร้ายแรงกว่าด้วย
log หลังรีบูต
หากไม่มีไดเรกทอรี /var/log/journal และใน /etc/systemd/journald.conf ตั้ง Storage=auto log จะเก็บเฉพาะในหน่วยความจำ (/run/log/journal) และหายไปเมื่อรีบูต หากต้องการให้คงอยู่ ตั้ง Storage=persistent หรือสร้างไดเรกทอรีแล้วรีสตาร์ต journald ขนาดถูกจำกัดด้วย SystemMaxUse= และล้าง log เก่าด้วย journalctl --vacuum-time=2weeks หรือ --vacuum-size=500M
journald มักทำงานคู่กับ rsyslog: journald ส่งข้อความให้ rsyslog ซึ่งเขียนไฟล์ข้อความแบบดั้งเดิมไว้ใน /var/log/ และส่ง log ไปยังเซิร์ฟเวอร์กลางได้
เปิดบริการของคุณเองอัตโนมัติ: ตัวอย่าง unit file
สมมติคุณมีแอปพลิเคชัน (script หรือไบนารี) ที่ต้องทำงานตลอดเวลา เปิดขึ้นเองเมื่อบูต และรีสตาร์ตเมื่อล้มเหลว สร้างไฟล์ /etc/systemd/system/myapp.service:
[Unit]
Description=My web application
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
EnvironmentFile=/etc/myapp/env
ExecStart=/opt/myapp/bin/server --port 8080
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
อธิบายแต่ละส่วน:
- [Unit] — คำอธิบายและ dependency
After=กำหนดเพียงลำดับWants=คือ dependency แบบอ่อน (ดึง unit ขึ้นมา แต่ไม่ล้มถ้า unit นั้นเริ่มไม่ได้) dependency แบบแข็งคือRequires= - [Service] — วิธีรัน
Type=simpleหมายความว่าโปรเซสในExecStartคือตัวบริการเองและไม่แยกไปอยู่เบื้องหลังUser=รันด้วยผู้ใช้ที่ไม่มีสิทธิ์พิเศษRestart=on-failureรีสตาร์ตบริการหากออกด้วยข้อผิดพลาด หลังจากRestartSecวินาที - [Install] — สิ่งที่
enableจะทำWantedBy=multi-user.targetหมายความว่า "เริ่มเมื่อบูตตามปกติ"
นำไปใช้:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin myapp
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
systemctl status myapp
journalctl -u myapp -f
ข้อผิดพลาดที่พบบ่อยใน unit file
- พาธสัมพัทธ์ใน ExecStart พาธของโปรแกรมต้องเป็นแบบสัมบูรณ์ systemd ไม่ค้นหาคำสั่งใน
PATHของผู้ใช้เหมือนที่ shell ทำ - ลืม daemon-reload หลังแก้ไฟล์ systemd ยังใช้ค่าเดิม และจะเตือนใน
status - daemon แยกไปอยู่เบื้องหลังเอง หากโปรแกรม fork ตัวเองแต่ระบุ
Type=simplesystemd จะคิดว่าบริการจบแล้ว ให้รันโปรแกรมในโหมด foreground หรือใช้Type=forkingกับPIDFile= - ตัวแปรสภาพแวดล้อมจาก profile บริการไม่อ่าน
~/.bashrcและ/etc/profileต้องกำหนดตัวแปรด้วยEnvironment=หรือEnvironmentFile=
แทนที่ค่าโดยไม่แก้ unit ของแพ็กเกจ
หากต้องการเปลี่ยนพารามิเตอร์ของบริการที่มาจากแพ็กเกจ โดยไม่แตะไฟล์ของมัน ใช้ drop-in:
sudo systemctl edit nginx
โปรแกรมแก้ไขจะเปิดขึ้น และการเปลี่ยนแปลงจะถูกบันทึกใน /etc/systemd/system/nginx.service.d/override.conf เช่น เพิ่ม [Service] และ Restart=always เมื่อออกจากโปรแกรมแก้ไข systemd จะโหลดการตั้งค่าใหม่ให้เอง
Timer ของ systemd แทน cron
Timer คือ unit ที่รันบริการชื่อเดียวกันตามกำหนดเวลา ข้อดีเหนือ cron คือ log ของงานอยู่ใน journal มี dependency ได้ และสามารถรันชดเชยงานที่พลาดไปได้ (Persistent=true) ตัวอย่างการสำรองข้อมูลทุกวัน:
# /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers
ตรวจสอบรูปแบบ OnCalendar ได้ด้วย systemd-analyze calendar "*-*-* 03:00:00" ซึ่งจะแสดงเวลาที่จะรันครั้งถัดไป
วินิจฉัยการบูต
systemd เก็บเวลาเริ่มทำงานของแต่ละ unit ทำให้หาสาเหตุของการบูตช้าได้ง่าย:
systemd-analyze # เวลาบูตรวม
systemd-analyze blame # unit เรียงตามเวลาเริ่มทำงาน
systemd-analyze critical-chain # สายงานที่ทำให้การบูตช้า
systemd-analyze verify /etc/systemd/system/myapp.service # ตรวจ unit file
สรุป
systemd คือ PID 1 และตัวจัดการบริการของ Linux ยุคใหม่ มันอธิบายทุกอย่างด้วย unit ควบคุมด้วย systemctl เก็บ log ลง journal ที่ journalctl อ่าน และสามารถรันงานด้วย timer แทน cron หากต้องการใช้ให้คล่อง เพียงเรียนรู้ status, enable --now, journalctl -u และเขียน unit file ง่ายๆ ที่มี Restart=on-failure ได้ ก็เพียงพอแล้ว systemd, journald และการทำ log ถูกสอนแบบลงมือทำในหลักสูตร Linux
คำถามที่พบบ่อย
จะรู้ได้อย่างไรว่าระบบใช้ systemd?
รัน ps -p 1 -o comm= หากผลลัพธ์เป็น systemd แสดงว่าระบบทำงานภายใต้ systemd นอกจากนี้ไดเรกทอรี /run/systemd/system จะมีอยู่เฉพาะเมื่อบูตด้วย systemd
systemctl restart ต่างจาก reload อย่างไร?
restart หยุดบริการแล้วเริ่มใหม่ การเชื่อมต่อจะขาดหาย ส่วน reload ขอให้บริการโหลดการตั้งค่าใหม่โดยไม่หยุด แต่ทำได้เฉพาะเมื่อ unit มี ExecReload
รันบริการ systemd ด้วยผู้ใช้ธรรมดาโดยไม่ต้องใช้ sudo ได้ไหม?
ได้ systemd มี instance ของผู้ใช้: วาง unit ไว้ใน ~/.config/systemd/user/ และจัดการด้วย systemctl --user หากต้องการให้ทำงานแม้ไม่มีเซสชันล็อกอิน ให้เปิด loginctl enable-linger สำหรับผู้ใช้นั้น
ทำไมบริการจึงอยู่ในสถานะ failed และจะรีเซ็ตอย่างไร?
หาสาเหตุใน journalctl -u ชื่อ -b และบรรทัด Active ของคำสั่ง status หลังแก้ไขแล้วให้เริ่มบริการใหม่ ส่วนการลบเครื่องหมาย failed โดยไม่ต้องรีสตาร์ต ใช้ systemctl reset-failed
log ของ systemd เก็บไว้ที่ไหนบนดิสก์?
หากตั้งให้เก็บถาวรจะอยู่ใน /var/log/journal/ เป็นรูปแบบไบนารี มิฉะนั้นจะอยู่ใน /run/log/journal/ ในหน่วยความจำ อ่านด้วย journalctl ไม่ควรใช้เครื่องมือประมวลผลข้อความทั่วไป
หัวข้อนี้สอนอย่างละเอียดพร้อมฝึกปฏิบัติในคอร์ส “Linux: с нуля до уверенного администрирования”
- systemd: как на самом деле запускаются сервисы в современном Linux
- Журналы и мониторинг: journald, rsyslog и sysstat