0Pricing
Linux Command Line & Bash Scripting Mastery · บทเรียน

การควบคุมบริการ systemd และการเขียนไฟล์ยูนิต

ควบคุมบริการด้วย systemctl และเขียนไฟล์ยูนิตกับตัวตั้งเวลาแบบกำหนดเองสำหรับดีมอนที่ทำงานด้วยสคริปต์

การควบคุมบริการ systemd และการเขียนไฟล์ยูนิต เป็นบทเรียน Linux Command Line & Bash Scripting Mastery ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Linux Command Line & Bash Scripting Mastery และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Linux Command Line & Bash Scripting Mastery มีบทเรียนทั้งหมด 4 บทเรียน

บทนำสู่ systemd และ systemctl

systemd คือระบบเริ่มต้นระบบและตัวจัดการบริการที่ดิสทริบิวชัน Linux สมัยใหม่ส่วนใหญ่ใช้ โดยรับผิดชอบการเริ่ม หยุด และจัดการบริการของระบบ รวมถึงการจัดการลำดับการบูตและสถานะของระบบ

เครื่องมือหลักสำหรับโต้ตอบกับ systemd คือ systemctl ซึ่งช่วยให้คุณสามารถ:

  • เริ่มและหยุดบริการ
  • เปิดหรือปิดการเริ่มบริการเมื่อบูต
  • ตรวจสอบสถานะบริการและบันทึกการทำงาน
  • โหลดการกำหนดค่าใหม่โดยไม่ต้องเริ่มระบบบริการใหม่

บริการทั้งหมดที่ systemd จัดการจะกำหนดไว้ในไฟล์ยูนิต ซึ่งเป็นไฟล์การกำหนดค่าแบบประกาศที่จัดเก็บไว้ใน /etc/systemd/system/ (ทั้งระบบ) หรือ ~/.config/systemd/user/ (รายผู้ใช้)

คำสั่ง systemctl ที่จำเป็น

คำสั่ง systemctl เหล่านี้เป็นคำสั่งที่ใช้บ่อยที่สุดสำหรับการจัดการบริการในแต่ละวัน แต่ละคำสั่งทำงานกับ ชื่อหน่วย เช่น nginx.service หรือเพียง nginxnginx.

  • systemctl start <unit> — เริ่มบริการทันที
  • systemctl stop <unit> — หยุดบริการที่กำลังทำงานอยู่
  • systemctl restart <unit> — หยุดแล้วเริ่มใหม่ (เริ่มใหม่ทั้งหมด)
  • systemctl reload <unit> — ส่ง SIGHUP เพื่อโหลดการตั้งค่าใหม่โดยไม่หยุดบริการ
  • systemctl enable <unit> — สร้างลิงก์สัญลักษณ์เพื่อให้หน่วยเริ่มทำงานเมื่อบูต
  • systemctl disable <unit> — ลบลิงก์สัญลักษณ์เหล่านั้น
  • systemctl status <unit> — แสดงสถานะ PID และบรรทัดบันทึกล่าสุด
#!/usr/bin/env bash
# Quick reference: inspect and control an nginx service
# (Requires nginx to be installed; run as root or with sudo)

systemctl status nginx
systemctl start nginx
systemctl enable nginx
systemctl reload nginx
systemctl restart nginx
systemctl stop nginx
systemctl disable nginx

ตรวจสอบสถานะบริการโดยละเอียด

systemctl status แสดงภาพรวมโดยละเอียดของหน่วย การทำความเข้าใจผลลัพธ์เป็นสิ่งสำคัญสำหรับการวิเคราะห์ปัญหาอย่างรวดเร็ว

  • Loaded: เส้นทางไปยังไฟล์หน่วยและระบุว่าเปิดใช้งานเมื่อบูตหรือไม่
  • Active: สถานะปัจจุบัน — active (running), inactive (dead), failed
  • Main PID: ตัวระบุกระบวนการของกระบวนการหลักของบริการ
  • CGroup: กระบวนการลูกทั้งหมดที่อยู่ภายใต้บริการ
  • บรรทัดบันทึก: รายการบันทึกล่าสุดของหน่วยนี้

คุณยังสามารถเรียกดูเฉพาะสถานะการทำงานด้วย systemctl is-active และสถานะการเปิดใช้งานด้วย systemctl is-enabled ซึ่งเหมาะอย่างยิ่งสำหรับใช้ในสคริปต์

#!/usr/bin/env bash
# Script-friendly service health check
SERVICE="sshd"

if systemctl is-active --quiet "$SERVICE"; then
    echo "$SERVICE is running."
else
    echo "$SERVICE is NOT running. Attempting restart..."
    systemctl restart "$SERVICE"
fi

if systemctl is-enabled --quiet "$SERVICE"; then
    echo "$SERVICE is enabled at boot."
else
    echo "WARNING: $SERVICE is not enabled at boot."
fi

แสดงรายการและกรองหน่วย

เมื่อจัดการบริการจำนวนมาก คุณจำเป็นต้องมีวิธีแสดงรายการและกรองหน่วยอย่างมีประสิทธิภาพ systemctl list-units จะแสดงหน่วยทั้งหมดที่โหลดอยู่ในปัจจุบัน ส่วน list-unit-files จะแสดงไฟล์หน่วยทั้งหมดที่ติดตั้งไว้พร้อมสถานะการเปิดใช้งาน

ตัวเลือกการกรองที่มีประโยชน์:

  • --type=service — แสดงเฉพาะหน่วยบริการ
  • --state=failed — แสดงเฉพาะหน่วยที่ล้มเหลว
  • --state=active — แสดงเฉพาะหน่วยที่กำลังทำงาน
  • --all — รวมหน่วยที่ไม่ได้ทำงานไว้ในรายการ

การใช้ตัวกรองเหล่านี้ร่วมกับ grep ช่วยให้คุณสร้างกระบวนการตรวจสอบที่มีประสิทธิภาพในสคริปต์บำรุงรักษาได้

#!/usr/bin/env bash
# List all failed services and report them
echo "=== Failed Services ==="
systemctl list-units --type=service --state=failed --no-legend

echo ""
echo "=== Services Enabled at Boot ==="
systemctl list-unit-files --type=service --state=enabled --no-legend | awk '{print $1}'

โครงสร้างของไฟล์หน่วยบริการ systemd

ไฟล์หน่วยบริการ เป็นไฟล์ข้อความธรรมดารูปแบบ INI ที่ประกอบด้วยส่วนต่าง ๆ แต่ละส่วนควบคุมแง่มุมที่แตกต่างกันของวงจรการทำงานของหน่วย

  • [Unit] — ข้อมูลกำกับ: คำอธิบายและข้อกำหนดด้านลำดับการทำงาน (After=, Requires=, Wants=)
  • [Service] — วิธีเริ่มและหยุดกระบวนการ: ExecStart, ExecStop, Restart, User, WorkingDirectory
  • [Install] — เวลาที่ควรเปิดใช้งานหน่วยนี้: WantedBy=multi-user.target หมายความว่าหน่วยจะเริ่มทำงานระหว่างการบูตแบบผู้ใช้หลายคนตามปกติ

หลังจากวางหรือแก้ไขไฟล์หน่วยใน /etc/systemd/system/ แล้ว คุณต้องเรียกใช้ systemctl daemon-reload เพื่อให้ systemd รับการเปลี่ยนแปลง

เขียนไฟล์หน่วยบริการไฟล์แรกของคุณ

มาสร้างไฟล์หน่วยบริการอย่างง่ายสำหรับสคริปต์เซิร์ฟเวอร์ HTTP ที่เขียนด้วย Python กัน ไฟล์หน่วยจะบอก systemd อย่างชัดเจนว่าต้องจัดการกระบวนการนี้อย่างไร ราวกับเป็นบริการระบบอื่น ๆ

คำสั่งกำกับ [Service] สำคัญที่ใช้ในตัวอย่างนี้:

  • Type=simple — systemd ถือว่ากระบวนการ ExecStart เป็นกระบวนการหลัก
  • User=www-data — ให้ทำงานภายใต้บัญชีที่ไม่ใช่ root เพื่อความปลอดภัย
  • WorkingDirectory — กำหนดไดเรกทอรีทำงานของกระบวนการ
  • Restart=on-failure — เริ่มใหม่โดยอัตโนมัติหากกระบวนการจบลงด้วยรหัสที่ไม่ใช่ศูนย์
  • RestartSec=5 — รอ 5 วินาทีระหว่างความพยายามเริ่มใหม่แต่ละครั้ง
#!/usr/bin/env bash
# Create a custom service unit file for a simple HTTP server
# Run as root

cat > /etc/systemd/system/mywebserver.service << 'EOF'
[Unit]
Description=My Custom Python Web Server
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/mysite
ExecStart=/usr/bin/python3 -m http.server 8080
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now mywebserver.service
systemctl status mywebserver.service

ประเภทบริการและวงจรการทำงานของกระบวนการ

คำสั่งกำกับ Type= ใน [Service] บอก systemd ว่าจะติดตามได้อย่างไรว่าบริการเริ่มทำงานเสร็จแล้ว การเลือกประเภทไม่ถูกต้องเป็นสาเหตุทั่วไปของปัญหาลำดับการทำงาน

  • Type=simple — ค่าเริ่มต้น systemd ถือว่าบริการเริ่มทำงานทันทีที่เปิดใช้ ExecStart โดยไม่ต้องมีสัญญาณความพร้อม
  • Type=forking — กระบวนการ ExecStart แยกกระบวนการแล้วจบลง ส่วนดีมอนตัวจริงทำงานเป็นกระบวนการลูก ให้ใช้ PIDFile= เพื่อให้ systemd ติดตามได้
  • Type=notify — กระบวนการส่ง sd_notify(READY=1) เมื่อพร้อมทำงานจริง เชื่อถือได้มากที่สุดสำหรับดีมอนที่ซับซ้อน
  • Type=oneshot — ทำงานครั้งเดียวแล้วจบลง หน่วยถัดไปจะรอให้ทำงานเสร็จ เหมาะสำหรับสคริปต์ตั้งค่า
  • Type=idle — คล้าย simple แต่จะหน่วงการทำงานจนกว่างานที่กำลังทำงานอยู่ทั้งหมดจะเสร็จสิ้น
#!/usr/bin/env bash
# Example: oneshot service for a database migration script
# /etc/systemd/system/db-migrate.service

cat > /etc/systemd/system/db-migrate.service << 'EOF'
[Unit]
Description=Run Database Migrations
After=postgresql.service
Requires=postgresql.service

[Service]
Type=oneshot
User=appuser
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/scripts/migrate.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl start db-migrate.service

ตัวแปรสภาพแวดล้อมและการเสริมความปลอดภัย

ไฟล์หน่วยบริการรองรับคำสั่งกำกับหลายรายการสำหรับส่งตัวแปรสภาพแวดล้อมและใช้ข้อจำกัดด้านความปลอดภัย ซึ่งทั้งสองอย่างมีความสำคัญต่อระบบที่ใช้งานจริง

คำสั่งกำกับสภาพแวดล้อม:

  • Environment="KEY=value" — กำหนดตัวแปรเดียวในบรรทัดคำสั่ง
  • EnvironmentFile=/etc/myapp/env — โหลดตัวแปรจากไฟล์ (หนึ่ง KEY=value ต่อบรรทัด)

คำสั่งกำกับสำหรับเสริมความปลอดภัยที่ใช้บ่อย:

  • NoNewPrivileges=true — ป้องกันไม่ให้กระบวนการได้รับสิทธิ์เพิ่มเติมผ่าน setuid
  • ProtectSystem=strict — เมานต์ /usr, /boot, /etc เป็นแบบอ่านอย่างเดียว
  • PrivateTmp=true — จัดเตรียม /tmp ที่แยกเฉพาะสำหรับบริการ
  • CapabilityBoundingSet= — ลบความสามารถทั้งหมดของ Linux
#!/usr/bin/env bash
# Hardened service unit with environment file

cat > /etc/systemd/system/secureapp.service << 'EOF'
[Unit]
Description=Secure Application Daemon
After=network.target

[Service]
Type=simple
User=secureapp
Group=secureapp
WorkingDirectory=/opt/secureapp
EnvironmentFile=/etc/secureapp/env
ExecStart=/opt/secureapp/bin/server
Restart=on-failure
RestartSec=10

# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
CapabilityBoundingSet=
ReadWritePaths=/var/lib/secureapp /var/log/secureapp

[Install]
WantedBy=multi-user.target
EOF

# Create the environment file separately so secrets stay out of the unit file
install -m 600 -o secureapp /dev/null /etc/secureapp/env
echo 'APP_PORT=9000' >> /etc/secureapp/env
echo 'DB_URL=postgresql://localhost/mydb' >> /etc/secureapp/env

systemctl daemon-reload

บทนำสู่หน่วยตัวจับเวลาของ systemd

ตัวจับเวลา systemd คือหน่วยที่เปิดใช้งานหน่วยอื่น (โดยปกติคือ .service) ตามกำหนดเวลา โดยมาแทนงาน cron แบบดั้งเดิมด้วยกลไกที่ผสานรวม บันทึกข้อมูล และควบคุมได้ดียิ่งขึ้น

หน่วยตัวจับเวลาทุกหน่วย (foo.timer) จะจับคู่กับหน่วยบริการที่ใช้ชื่อพื้นฐานเดียวกัน (foo.service) ซึ่งเป็นผู้ดำเนินงานจริง คุณต้องเปิดใช้งานและเริ่มต้น ตัวจับเวลา ไม่ใช่บริการโดยตรง

ประเภทตัวจับเวลา:

  • ตัวจับเวลาแบบเวลาจริง (ปฏิทิน) — ทำงานตามเวลานาฬิกาโดยใช้เอกซ์เพรสชัน OnCalendar= เช่น daily, weekly หรือ Mon *-*-* 02:00:00
  • ตัวจับเวลาแบบสัมพันธ์ — ทำงานโดยอ้างอิงเหตุการณ์ของระบบผ่าน OnBootSec=, OnActiveSec= หรือ OnUnitActiveSec=

เขียนไฟล์หน่วยตัวจับเวลา

มาสร้างคู่ตัวจับเวลาและบริการที่ทำงานครบถ้วนสำหรับเรียกใช้สคริปต์สำรองข้อมูลทุกวันที่เวลา 02:00 กัน โปรดสังเกตว่าส่วน [Timer] อยู่ในไฟล์ .timer ของตัวเอง ขณะที่งานอยู่ในไฟล์ .service ที่จับคู่กัน

คำสั่งกำกับ [Timer] สำคัญ:

  • OnCalendar= — เอกซ์เพรสชันปฏิทินสำหรับกำหนดเวลา
  • Persistent=true — หากระบบปิดอยู่ในเวลาที่ตัวจับเวลาควรทำงาน ให้ทำงานทันทีเมื่อบูตครั้งถัดไป
  • RandomizedDelaySec= — เพิ่มช่วงหน่วงแบบสุ่มสูงสุด N วินาที เพื่อป้องกันไม่ให้โฮสต์จำนวนมากทำงานพร้อมกันตามกำหนดเวลาเดียวกัน
  • Unit= — หน่วยเป้าหมายที่ระบุอย่างชัดเจน (ไม่จำเป็นหากชื่อเหมือนกัน)
#!/usr/bin/env bash
# Create a daily backup timer pair
# Run as root

# 1. The service that does the work
cat > /etc/systemd/system/daily-backup.service << 'EOF'
[Unit]
Description=Daily Database Backup
After=network.target postgresql.service

[Service]
Type=oneshot
User=backup
ExecStart=/usr/local/bin/backup-db.sh
StandardOutput=journal
StandardError=journal
EOF

# 2. The timer that schedules it
cat > /etc/systemd/system/daily-backup.timer << 'EOF'
[Unit]
Description=Run Daily Database Backup at 02:00

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
RandomizedDelaySec=300

[Install]
WantedBy=timers.target
EOF

systemctl daemon-reload
systemctl enable --now daily-backup.timer

# Verify
systemctl list-timers daily-backup.timer

ตรวจสอบบันทึกและแก้ไขปัญหาหน่วย

systemd ส่งผลลัพธ์ทั้งหมดของบริการไปยัง เจอร์นัล ซึ่งคุณเรียกดูได้ด้วย journalctl วิธีนี้รวมบันทึกจากทุกหน่วยไว้ในแหล่งข้อมูลเดียวที่ค้นหาได้

ตัวเลือก journalctl ที่จำเป็นสำหรับแก้ไขปัญหาบริการ:

  • -u <unit> — กรองตามชื่อหน่วย
  • -f — ติดตามบันทึกแบบเรียลไทม์ (เช่น tail -f)
  • -n 50 — แสดงเฉพาะ 50 บรรทัดสุดท้าย
  • --since "1 hour ago" — จำกัดตามเวลา
  • -p err — แสดงเฉพาะข้อผิดพลาดและระดับที่รุนแรงกว่า
  • -b — แสดงเฉพาะบันทึกจากการบูตครั้งปัจจุบัน

เมื่อหน่วยเริ่มทำงานไม่สำเร็จ สิ่งแรกที่ควรเรียกใช้คือ journalctl -u <unit> -n 30 --no-pager ตามด้วย systemctl status <unit> เพื่อเก็บบริบทของข้อผิดพลาดล่าสุด

#!/usr/bin/env bash
# Troubleshooting helper: dump unit status and recent logs
# Usage: ./service-debug.sh <unit-name>

UNIT="${1:-nginx.service}"

echo "=============================="
echo "STATUS: $UNIT"
echo "=============================="
systemctl status "$UNIT" --no-pager -l

echo ""
echo "=============================="
echo "RECENT LOGS (last 50 lines): $UNIT"
echo "=============================="
journalctl -u "$UNIT" -n 50 --no-pager

echo ""
echo "=============================="
echo "ERRORS ONLY (current boot)"
echo "=============================="
journalctl -u "$UNIT" -b -p err --no-pager

ทดสอบความรู้: ไฟล์หน่วย systemd

ทดสอบความเข้าใจของคุณเกี่ยวกับการกำหนดค่าหน่วยบริการและหน่วยตัวจับเวลาของ systemd

ทบทวนบทเรียน: ควบคุมบริการ systemd และเขียนไฟล์หน่วย

ในบทเรียนนี้ คุณได้ศึกษาหลักการสำคัญของการจัดการบริการ systemd และการเขียนไฟล์หน่วยในระดับมืออาชีพ ต่อไปนี้คือสรุปเนื้อหาที่ครอบคลุม:

  • พื้นฐาน systemctl — start, stop, restart, reload, enable, disable, status, is-active และ is-enabled สำหรับการตรวจสอบที่เหมาะกับการใช้ในสคริปต์
  • การแสดงรายการและการกรอง — ใช้ list-units และ list-unit-files ร่วมกับตัวเลือก --type และ --state เพื่อแยกบริการที่ล้มเหลวหรือเปิดใช้งานอยู่
  • โครงสร้างไฟล์หน่วย — สามส่วน ได้แก่ [Unit], [Service] และ [Install] พร้อมคำสั่งกำกับสำคัญ
  • ประเภทบริการ — simple, forking, notify, oneshot และเวลาที่ควรใช้แต่ละประเภท
  • สภาพแวดล้อมและความปลอดภัย — EnvironmentFile, NoNewPrivileges, ProtectSystem, PrivateTmp สำหรับดีมอนที่เสริมความปลอดภัย
  • หน่วยตัวจับเวลา — การจับคู่ไฟล์ .timer และ .service, เอกซ์เพรสชัน OnCalendar และพฤติกรรมทำงานชดเชยของ Persistent
  • Journalctl — การกรองตามหน่วย เวลา การบูต และระดับความสำคัญ เพื่อวิเคราะห์ความล้มเหลวได้อย่างมีประสิทธิภาพ

ด้วยทักษะเหล่านี้ คุณจะสามารถจัดการบริการระบบใด ๆ กำหนดเวลางานที่ทำซ้ำได้อย่างน่าเชื่อถือ และเขียนไฟล์หน่วยระดับใช้งานจริงสำหรับดีมอนของคุณเอง

คำถามที่พบบ่อย

บทเรียน “การควบคุมบริการ systemd และการเขียนไฟล์ยูนิต” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การควบคุมบริการ systemd และการเขียนไฟล์ยูนิต” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Linux Command Line & Bash Scripting Mastery ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Linux Command Line & Bash Scripting Mastery มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การควบคุมบริการ systemd และการเขียนไฟล์ยูนิต”

ควบคุมบริการด้วย systemctl และเขียนไฟล์ยูนิตกับตัวตั้งเวลาแบบกำหนดเองสำหรับดีมอนที่ทำงานด้วยสคริปต์ คุณปฏิบัติ Linux Command Line & Bash Scripting Mastery ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Linux Command Line & Bash Scripting Mastery หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Linux Command Line & Bash Scripting Mastery บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “การควบคุมบริการ systemd และการเขียนไฟล์ยูนิต” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Linux Command Line & Bash Scripting Mastery นี้ได้ไหม

ได้ บทเรียน Linux Command Line & Bash Scripting Mastery ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การทำงานอัตโนมัติสำหรับการจัดเตรียมผู้ใช้และกลุ่ม
  2. การควบคุมบริการ systemd และการเขียนไฟล์ยูนิต
  3. การทำงานอัตโนมัติด้านดิสก์ ระบบไฟล์ และการเมานต์
  4. การสร้างสคริปต์ตรวจสอบสุขภาพระบบและแจ้งเตือน
← กลับไปที่ Linux Command Line & Bash Scripting Mastery