็†ฑ้–€ๅˆ†้กž
 ่ผ‰ๅ…ฅไธญ…
็›ฎ้Œ„

๐Ÿงฑ Linux systemctl ่ˆ‡ๆœๅ‹™็ฎก็†ๅ…จๆ”ป็•ฅ(ๅซๅธธ่ฆ‹้Œฏ่ชค่ˆ‡่‡ชๅ‹•้‡ๅ•Ÿ่จญๅฎš)

    ๐Ÿงฑ Linux systemctl ่ˆ‡ๆœๅ‹™็ฎก็†ๅ…จๆ”ป็•ฅ(ๅซๅธธ่ฆ‹้Œฏ่ชค่ˆ‡่‡ชๅ‹•้‡ๅ•Ÿ่จญๅฎš)

    ้€™็ฏ‡ๆ•ด็† systemctl ็š„ๅธธ็”จ่ˆ‡้€ฒ้šŽๆ“ไฝœ:ๅพž ๆŸฅ่ฉข่ˆ‡ๆŽงๅˆถๆœๅ‹™้–‹ๆฉŸ่‡ชๅ•Ÿ่‡ชๅ‹•้‡ๅ•Ÿ็ญ–็•ฅ่ฆ†ๅฏซ drop-in ๅˆฐ journalctl ๆŽ’้ŒฏTimer ๆŽ’็จ‹ๅฎ‰ๅ…จๅผทๅŒ–,ๆไพ›ๅฏ็›ดๆŽฅ่ค‡่ฃฝ็š„ๆŒ‡ไปค่ˆ‡็ฏ„ไพ‹ๅ–ฎๅ…ƒๆช”。

    ๐Ÿ“‘ ็›ฎ้Œ„

    ไธ€、ๅธธ็”จ systemctl ๆŒ‡ไปค้€ŸๆŸฅ

    # ๅ•Ÿๅ‹• / ๅœๆญข / ้‡ๆ–ฐๅ•Ÿๅ‹• / ้‡ๆ–ฐ่ผ‰ๅ…ฅ่จญๅฎš
    sudo systemctl start nginx
    sudo systemctl stop nginx
    sudo systemctl restart nginx
    sudo systemctl reload nginx
    
    # ๆŸฅ็œ‹็‹€ๆ…‹่ˆ‡ๅณๆ™‚ๆ—ฅ่ชŒ
    systemctl status nginx
    journalctl -u nginx -f
    
    # ๆŸฅ็œ‹ๆ˜ฏๅฆ้–‹ๆฉŸ่‡ชๅ•Ÿ;่จญๅฎš้–‹ๆฉŸ่‡ชๅ•Ÿ / ๅ–ๆถˆ
    systemctl is-enabled nginx
    sudo systemctl enable nginx
    sudo systemctl disable nginx
    
    # ๅˆ—ๅ‡บๆœๅ‹™、ๅฅ—็”จ่ฎŠๆ›ด
    systemctl list-units --type=service --state=running
    sudo systemctl daemon-reload
    
    # ๆŸฅ็œ‹ๅ–ฎๅ…ƒๆช”่ˆ‡ไพ่ณด
    systemctl cat nginx.service
    systemctl list-dependencies multi-user.target
    

    ไบŒ、้–‹ๆฉŸ่‡ชๅ‹•ๅ•Ÿๅ‹•่ˆ‡็›ฎๆจ™(target)

    enable ๆœƒๅปบ็ซ‹ WantedBy ็›ฎๆจ™(้€šๅธธ multi-user.target),่ฎ“ๆœๅ‹™ๆ–ผ้–‹ๆฉŸๆ™‚่ผ‰ๅ…ฅ。

    # ็›ฎๅ‰้ ่จญ target ่ˆ‡ๅˆ‡ๆ›
    systemctl get-default
    sudo systemctl set-default multi-user.target
    sudo systemctl isolate rescue.target   # ็ซ‹ๅณๅˆ‡ๆ›ๅˆฐ็ถญ่ญทๆจกๅผ

    ไธ‰、่‡ชๅ‹•้‡ๅ•Ÿ็ญ–็•ฅ(Restart=)ๆœ€ไฝณๅฏฆๅ‹™

    • Restart=on-failure:้ž 0 ็ตๆŸ็ขผๆ™‚้‡ๅ•Ÿ,ๆœ€ๅธธ็”จ。
    • Restart=always:ไปปไฝ•็ตๆŸ้ƒฝ้‡ๅ•Ÿ,็”จๆ–ผ้•ท้ง、้ ˆ้ซ˜ๅฏ็”จ็š„ๆœๅ‹™。
    • RestartSec=:้‡ๅ•Ÿ้–“้š”;StartLimitIntervalSec=StartLimitBurst= ้˜ฒๆญข็˜‹็‹‚้‡ๅ•Ÿ。
    • ๅŠ ไธŠ RuntimeMaxSec= ๆˆ–ๅฅๅบทๆชขๆŸฅ่…ณๆœฌ,้ฟๅ…ๆœๅ‹™ๅกๆญป็„กๆ„Ÿ。

    ๅ››、Service Unit ๆจฃๆฟ:็ฉฉๅฎš、ๅฏๅ›žๅพฉ、ๅฏ่ง€ๆธฌ

    ๐Ÿ“„ ้ปžๆˆ‘ๅฑ•้–‹็ฏ„ไพ‹(ๅปบ่ญฐ่ค‡่ฃฝๅพŒไพๅฏฆ้š›่ทฏๅพ‘่ˆ‡ไฝฟ็”จ่€…่ชฟๆ•ด)
    [Unit]
    Description=My Web App
    After=network-online.target
    Wants=network-online.target
    
    [Service]
    Type=simple
    User=www-data
    WorkingDirectory=/opt/myapp
    ExecStart=/usr/bin/python3 /opt/myapp/app.py
    # --- ้‡ๅ•Ÿ็ญ–็•ฅ ---
    Restart=on-failure
    RestartSec=3
    StartLimitIntervalSec=60
    StartLimitBurst=5
    # --- ็’ฐๅขƒ่ˆ‡ๆ—ฅ่ชŒ ---
    Environment="ENV=prod" "PORT=8080"
    StandardOutput=journal
    StandardError=journal
    # --- ๆฒ™็ฎฑๅŒ–(่ฆ‹ไธ‹็ฏ€ Hardening)---
    NoNewPrivileges=true
    PrivateTmp=true
    ProtectSystem=full
    ProtectHome=true
    
    [Install]
    WantedBy=multi-user.target

    ไบ”、ไธๆ”นๅŽŸๆช”็š„่ฆ†ๅฏซ:drop-in(systemctl edit)

    ไธ่ฆๆ”นๅฅ—ไปถๆไพ›็š„ /usr/lib/systemd/system/*.service;็”จ drop-in ๆ›ดๅฎ‰ๅ…จ。

    sudo systemctl edit myapp.service
    # ๆœƒ้–‹ๅ•Ÿ /etc/systemd/system/myapp.service.d/override.conf
    # ๅชๆ”พๅทฎ็•ฐ:
    [Service]
    Restart=always
    Environment="DEBUG=false"
    
    # ๅฅ—็”จ
    sudo systemctl daemon-reload
    sudo systemctl restart myapp.service
    systemctl cat myapp.service

    ๅ…ญ、ๅธธ่ฆ‹้Œฏ่ชค่ˆ‡ๆŽ’ๆŸฅๆธ…ๅ–ฎ

    • ๐Ÿ”Œ ๅ•Ÿๅ‹•ๅกไฝ:็ผบ Wants=network-online.target ๆˆ–ๆœชๆญฃ็ขบ็ญ‰ๅพ…็ถฒ่ทฏ;ๆชขๆŸฅ NetworkManager-wait-online ๆˆ– systemd-networkd-wait-online
    • ๐Ÿ— ๆฌŠ้™้Œฏ่ชค:ๆœๅ‹™ User= ๆŒ‡ๅฎšๅธณ่™Ÿๆ˜ฏๅฆๆ“ๆœ‰็›ฎ้Œ„่ˆ‡ๆช”ๆกˆๆฌŠ้™;็”จ chown/chmod ไฟฎๆญฃ。
    • ๐Ÿ“ ่ทฏๅพ‘ไธๅญ˜ๅœจ:ๅœจ ExecStartPre=/usr/bin/mkdir -p /var/lib/myapp ๅ…ˆๅปบ็ซ‹。
    • ๐Ÿ‘ป Type ่จญ้Œฏ:ๅ‚ณ็ตฑ daemon ๆ‡‰ Type=forking;ๆœ‰้€š็ŸฅๆฉŸๅˆถๆ‰็”จ notify
    • ๐Ÿ” ็„ก้™้‡ๅ•Ÿ:่ชฟๆ•ด RestartSecStartLimit*,ไธฆ็”จ journalctl -xeu ๆ‰พๆ นๅ› 。

    ไธƒ、journalctl ่ˆ‡ๅ•Ÿๅ‹•่€—ๆ™‚ๅˆ†ๆž

    # ็•ถๆฌก้–‹ๆฉŸ็š„้‡่ฆ่จŠๆฏ
    journalctl -b -p warning
    
    # ่ฟฝๆœๅ‹™ๆ—ฅ่ชŒ(ๅณๆ™‚)
    journalctl -u myapp.service -f
    
    # ๅ•Ÿๅ‹•่€—ๆ™‚็ธฝ่ฆฝ่ˆ‡้—œ้ต้ˆ
    systemd-analyze
    systemd-analyze blame
    systemd-analyze critical-chain
    
    # ่ผธๅ‡บๅ•Ÿๅ‹•ๆต็จ‹ๅœ–(SVG)
    systemd-analyze plot > /tmp/boot.svg

    ๅ…ซ、Timer vs cron:ไบ‹ไปถๅผๆŽ’็จ‹่ˆ‡่ฃœ่ท‘

    ๐Ÿ•’ ็ฏ„ไพ‹:ๆฏๅคฉ 02:15 ๅŸท่กŒๅ‚™ไปฝ、้—œๆฉŸๆœŸ้–“่ฃœ่ท‘
    # /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=*-*-* 02:15:00
    Persistent=true
    RandomizedDelaySec=120
    
    [Install]
    WantedBy=timers.target
    
    # ๅ•Ÿ็”จ
    sudo systemctl enable --now backup.timer
    systemctl list-timers --all

    ไน、ๆœๅ‹™ๆฒ™็ฎฑ่ˆ‡่ณ‡ๆบ้™ๅˆถ

    • ่ณ‡ๆบ้™ๅˆถCPUQuota=50%MemoryMax=1G
    • ๆฒ™็ฎฑๅŒ–้ธ้ …NoNewPrivileges=truePrivateTmp=trueProtectSystem=fullProtectHome=trueCapabilityBoundingSet=(ๆœ€ๅฐๆฌŠ้™)。
    • ่‡จๆ™‚้™ๅˆถๅŸท่กŒsystemd-run --scope -p CPUQuota=50% -p MemoryMax=1G <cmd>
    # ไปฅ 50% CPU、1G ่จ˜ๆ†ถ้ซ”้™ๅˆถๅŸท่กŒ
    sudo systemd-run --unit=limit-job --scope -p CPUQuota=50% -p MemoryMax=1G /usr/bin/some-task

    ๐Ÿ”Ž ๅธธ่ฆ‹ๅ•็ญ”(FAQ)

    Q1:ๆˆ‘ๆ”นไบ† unit ๆช”,ไฝ†ๆœๅ‹™ๆฒ’ๆœ‰ๅฅ—็”จ?
    ่ซ‹ๅ…ˆ sudo systemctl daemon-reload ๅ† restart。่ฎŠๆ›ดๆ‰ๆœƒ่ขซ่ผ‰ๅ…ฅ。

    Q2:ๆœๅ‹™ๅทฒ enable,็‚บไฝ•้–‹ๆฉŸๆฒ’ๆœ‰่ท‘?
    ๆชขๆŸฅ WantedBy ๆ‰€ๅฑฌ target ๆ˜ฏๅฆ็‚บ็ณป็ตฑ get-default ็š„ไพ้™„้ˆ;ๅฆๆŸฅ journalctl -b

    Q3:ๅฆ‚ไฝ•่ฎ“ oneshot ไปปๅ‹™ๅคฑๆ•—ไนŸ่ƒฝ้‡่ฉฆ?
    ๅœจ [Service] ไฝฟ็”จ Restart=on-failure ่ˆ‡ RestartSec=,ไธฆๅฐ‡้‚่ผฏๆ‹†็‚บๅฏ้‡ๅ…ฅ。

    ๐Ÿงญ ่กŒๅ‹•ๆธ…ๅ–ฎ

    ✅ ๅฐ‡ๆ—ขๆœ‰ๆœๅ‹™ๅŠ ๅ…ฅ Restart ็ญ–็•ฅ่ˆ‡ StartLimit* ไฟ่ญท
    ✅ ไปฅ systemctl edit ๅปบ็ซ‹ drop-in ่ฆ†ๅฏซ(ไธๅ‹•ๅŽŸๆช”)
    ✅ ็”จ journalctl ่ˆ‡ systemd-analyze ๆชขๆŸฅ้–‹ๆฉŸ็“ถ้ ธ
    ✅ ้—œ้ตไปปๅ‹™ๆ”น็”จ Timer,ๅ•Ÿ็”จ Persistent ่ˆ‡ RandomizedDelaySec
    ✅ ๅฅ—็”จๆฒ™็ฎฑๅŒ–้ธ้ …่ˆ‡่ณ‡ๆบไธŠ้™(CPUQuota / MemoryMax)
      

    — WWFandy・็ณป็ตฑ็ฎก็†็ญ†่จ˜

    ๐Ÿ”— ๅˆ†ไบซ้€™็ฏ‡ LINE Facebook X

    ๆฒ’ๆœ‰็•™่จ€:

    ๅผต่ฒผ็•™่จ€

    ๅญ—็ดš