SSD Nodes Learn Hosting plans →
Hướng dẫn Matt ConnorBởi Matt Connor · Cập nhật ngày 2026-08-27

Lịch sử systemd: Vì sao systemd thắng SysV init

SysV init thiếu dependency và quản lý process; Upstart, launchd đi trước. Tìm hiểu vì sao các distro chuyển sang systemd trong 4 năm và phản đối nào đúng.

Vì sao systemd thắng

Lịch sử của systemd bắt đầu từ 2 việc mà SysV init không thể làm. SysV init (System V init, hệ thống khởi động Linux kế thừa từ Unix của AT&T) không có cách mô tả một service phụ thuộc vào những gì, cũng không biết process nào thuộc về một service sau khi service đó chạy. systemd giải quyết cả 2 việc bằng các tính năng của kernel mà shell script không thể truy cập: control group để theo dõi process và listening socket được mở sẵn để sắp xếp thứ tự khởi động. Phần còn lại của câu chuyện là cách 2 giải pháp này lan sang phần còn lại của userland. Đây cũng là lúc các phản đối bắt đầu xuất hiện, và một số phản đối trong đó là đúng.

SysV init thực sự đã làm gì

Trên hệ thống SysV, PID 1 (process ID 1, process đầu tiên kernel khởi động) đọc /etc/inittab, chọn một runlevel rồi chạy các script của runlevel đó. Các script nằm trong /etc/init.d/. Các symbolic link trong /etc/rc3.d/ quyết định script nào được chạy và chạy theo thứ tự nào, vì vậy /etc/rc3.d/S20nginx trỏ đến /etc/init.d/nginx và được gọi với argument start.

#!/bin/sh
### BEGIN INIT INFO
# Provides:          nginx
# Required-Start:    $local_fs $remote_fs $network $syslog
# Required-Stop:     $local_fs $remote_fs $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
### END INIT INFO

case "$1" in
  start)
    start-stop-daemon --start --quiet --pidfile /run/nginx.pid \
      --exec /usr/sbin/nginx
    ;;
  stop)
    start-stop-daemon --stop --quiet --retry TERM/30/KILL/5 \
      --pidfile /run/nginx.pid
    ;;
esac

20 trong S20nginx là vị trí, không phải dependency. Nó cho biết script này chạy sau S19 và trước S21. Nó không cho biết lý do, nên không có thành phần nào kiểm tra được điều đó. Hệ thống cũng không thể an toàn chạy đồng thời hai script không liên quan nếu chưa có người xác định rằng việc đó an toàn.

Chương trình rc chạy từng script theo thứ tự và chờ script kết thúc. Một script bị block 30 giây để chờ địa chỉ mạng sẽ làm toàn bộ quá trình boot bị block 30 giây, kể cả các service không bao giờ dùng mạng.

Header LSB (Linux Standard Base) ở đầu script đó là một nỗ lực khắc phục vấn đề này từ bên trong. Debian 6.0 vào năm 2011 đặt insserv làm mặc định: chương trình này đọc Required-Start từ từng script, xây dựng một graph rồi đánh lại số các symlink. Khi đó Debian có thể chạy đồng thời các script độc lập bằng startpar. Cách này có ích, nhưng chưa giải quyết vấn đề sâu hơn. Dependency vẫn phụ thuộc vào việc một script kết thúc. S20nginx trả về 0 chỉ có nghĩa là một shell function đã return. Nó không có nghĩa nginx đang nhận connection.

Năm vấn đề mà không init script nào có thể giải quyết

  • Khởi động song song. Sắp xếp theo tên file tạo ra một thứ tự toàn phần cho mọi service trên máy, nên thời gian boot bằng tổng thời gian của từng phần.
  • Trạng thái sẵn sàng. Start script kết thúc ngay sau khi fork daemon, không phải khi daemon đã có thể xử lý request, nên script tiếp theo thường khởi động quá sớm.
  • Giám sát tiến trình. Daemon fork 2 lần rồi process cha thoát, khiến daemon tách khỏi terminal và được gán lại cho PID 1. init thấy một child thoát nhưng không có liên kết đáng tin cậy với process còn tồn tại.
  • Khởi động theo nhu cầu. inetd (internet super-server) có thể khởi chạy daemon khi có connection đến, nhưng đây là một system riêng với file cấu hình riêng. Nó cũng không xử lý thứ tự khởi động của các thành phần khác trong quá trình boot.
  • Kiểm soát tài nguyên. Không có thành phần nào trong init script giới hạn được memory hoặc phần CPU của một service. ulimit chỉ áp dụng cho một process, còn nice chỉ tác động đến scheduler, nên một child chạy mất kiểm soát của service trông chẳng khác gì process khác trên máy.

Khoảng trống trong việc giám sát tiến trình là vấn đề gây ảnh hưởng hằng ngày nhiều nhất. PID file là cách khắc phục tạm thời: daemon ghi process ID của nó vào /run/nginx.pid, rồi hàm stop đọc lại file này. Nếu daemon bị kill cưỡng bức, file vẫn còn. Sau đó kernel có thể dùng lại số PID đó cho một process khác, và start-stop-daemon --stop --pidfile sẽ gửi signal đến process đang sở hữu PID này. PID file cũ là nguyên nhân khiến init script kill nhầm process.

launchd đã giải quyết vấn đề socket trước

Apple phát hành launchd trong Mac OS X 10.4 vào năm 2005. Dave Zarzycki viết phần mềm này. Một process thay thế init, rc, xinetd, crond và watchdogd.

Ý tưởng đáng học hỏi là socket activation. launchd tạo mọi listening socket trước, rồi mới khởi động các daemon. Client kết nối đến một daemon chưa khởi động sẽ không nhận lỗi connection refused, vì kernel giữ connection trong backlog queue của socket đó cho đến khi daemon gọi accept(). Con người không còn phải khai báo thứ tự giữa hai daemon. Socket tự xử lý việc này.

launchd được xây dựng trên Mach IPC (inter-process communication), một thành phần của kernel XNU của Apple và không có tương đương trên Linux. Việc port code này chưa bao giờ thực tế. Tuy vậy, ý tưởng vẫn được áp dụng.

Upstart lấy event làm đơn vị công việc

Upstart của Canonical, do Scott James Remnant viết, được phát hành cùng Ubuntu 6.10 vào tháng 10 năm 2006. Fedora 9 đến Fedora 14 sử dụng Upstart, cũng như RHEL 6 và Chrome OS. Upstart thay runlevel bằng event, còn job xác định những event nào sẽ khởi động và dừng job đó.

# /etc/init/example.conf
start on filesystem and net-device-up IFACE!=lo
stop on runlevel [!2345]
respawn
respawn limit 10 5
exec /usr/local/bin/exampled

Khi số lượng job tăng lên, hai vấn đề xuất hiện. Vấn đề đầu tiên là hướng phụ thuộc. Một job nói rằng “hãy khởi động tôi khi việc này xảy ra”, nên thông tin về thành phần nào phụ thuộc vào thành phần nào nằm trong file không phù hợp: service biết nó cần gì, nhưng không thể biết năm sau thành phần nào sẽ cần nó. Việc thêm một service thường buộc phải sửa một job hiện có để job đó phát ra event mới.

Vấn đề thứ hai là theo dõi tiến trình. Upstart theo dõi một daemon fork bằng cách đếm các lệnh gọi fork() với ptrace; bạn cấu hình việc này bằng expect fork hoặc expect daemon. Nếu đoán sai số lần fork, Upstart sẽ giám sát một process đã thoát hoặc chờ một lần fork đã xảy ra. Biểu hiện là initctl start bị treo mà không có lỗi, trong khi job file không cung cấp cách nào để giải thích việc đó.

Upstart cũng yêu cầu contributor ký thỏa thuận đóng góp của Canonical. Đây không phải lỗi kỹ thuật, nhưng nó có ảnh hưởng đến những người tham gia phát triển dự án.

Rethinking PID 1, tháng 4 năm 2010

Ngày 30 tháng 4 năm 2010, Lennart Poettering đăng một bài viết có tên “Rethinking PID 1”. Kay Sievers cùng ông phát triển dự án này. Lập luận gồm 4 phần.

  • Khởi động ít hơn. Nhiều service có thể chờ đến khi thực sự có yêu cầu sử dụng.
  • Không khai báo thứ tự khi socket đã có thể thể hiện thứ tự đó. Mở tất cả socket trong một lượt, sau đó khởi động mọi thứ cùng lúc.
  • Theo dõi process bằng control group thay vì PID file.
  • Mô tả service trong một file khai báo, để một mô tả hoạt động trên mọi distribution.

Bản phát hành đầu tiên ra mắt trong cùng năm. Fedora 14 phát hành kèm systemd dưới dạng tùy chọn vào tháng 11 năm 2010, còn Fedora 15 đặt systemd làm mặc định vào tháng 5 năm 2011.

Vì sao cgroups giúp cơ chế giám sát hoạt động đáng tin cậy

cgroup (control group) là một tính năng của kernel dùng để nhóm các process, được tích hợp vào Linux 2.6.24 vào năm 2008. systemd đặt mỗi service vào một cgroup riêng. Process con kế thừa cgroup của process cha, và process không có quyền đặc biệt không thể tự đưa mình ra khỏi cgroup đó. Vì vậy, double forking không thể che giấu process nào: PID 1 luôn nắm chính xác tập process thuộc một unit. Dừng một service nghĩa là kill toàn bộ process trong cgroup của service đó. Đây là chức năng mà KillMode=control-group cung cấp theo mặc định.

systemctl status in nhóm process đó:

● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
     Active: active (running) since Tue 2026-08-11 09:14:22 UTC; 3min ago
   Main PID: 1042 (nginx)
      Tasks: 3 (limit: 4653)
     Memory: 6.1M (peak: 7.4M)
     CGroup: /system.slice/nginx.service
             ├─1042 "nginx: master process /usr/sbin/nginx"
             ├─1043 "nginx: worker process"
             └─1044 "nginx: worker process"

Khối thông tin này giải quyết hoàn toàn vấn đề stale PID file. Không có file nào trở nên stale, vì danh sách này là trạng thái do kernel quản lý.

Cây process này cũng chứa các giới hạn tài nguyên, vì cgroups ban đầu được xây dựng cho việc accounting trước khi được dùng để tracking. MemoryMax=, CPUQuota= và TasksMax= mỗi lệnh chiếm một dòng. Đặt giới hạn cứng cho memory và CPU của một service hiện chỉ cần một drop-in file; còn vào năm 2009, việc này phải là một patch cho shell script mà không ai viết.

Vì sao mọi distribution đều chuyển đổi trong giai đoạn 2011–2015

  • Fedora 15, tháng 5 năm 2011.
  • openSUSE 12.1, tháng 11 năm 2011.
  • Mageia 2, tháng 5 năm 2012.
  • Arch Linux, mặc định cho các bản cài đặt mới từ tháng 10 năm 2012.
  • RHEL 7, tháng 6 năm 2014.
  • SLES 12, tháng 10 năm 2014.
  • Debian 8, tháng 4 năm 2015.
  • Ubuntu 15.04, tháng 4 năm 2015.

Bản RHEL 7 tồn tại lâu hơn các bản khác vì CentOS 7 đã rebuild nó. Đây cũng là nơi phần lớn quản trị viên lần đầu làm quen với unit file, một chặng trong câu chuyện dài bắt đầu từ Red Hat Linux, đi qua CentOS đến Rocky và AlmaLinux.

Lý do chủ yếu khá đơn giản, nên quá trình chuyển đổi diễn ra nhanh.

  • Một unit file hoạt động trên mọi distribution. Vì vậy, các dự án upstream bắt đầu phát hành file .service, còn các distribution không phải duy trì một shell script cho từng package trong từng release.
  • Việc theo dõi session desktop chuyển sang systemd-logind sau khi ConsoleKit không còn được duy trì vào khoảng năm 2012. GNOME cần logind, nên distribution không dùng systemd phải tìm một giải pháp thay thế. Giải pháp đó là elogind, được tách từ logind của systemd và duy trì riêng.
  • udev, device manager, được hợp nhất vào source tree của systemd vào tháng 4 năm 2012. Các distribution có udev giờ phải theo dõi repository của systemd. Gentoo đã fork eudev để đáp ứng việc này.
  • Container khiến việc theo dõi process đáng tin cậy và giới hạn theo từng service trở nên quan trọng hơn, vì cả hai đều là tính năng của cgroup. Câu hỏi supervisor nào sở hữu process trong container vẫn còn được đặt ra mỗi khi bạn cấu hình Docker Compose stack tự khởi động lại sau reboot.

Quyết định của Debian là quyết định gây nhiều chú ý nhất. Technical Committee bỏ phiếu vào tháng 2 năm 2014. Kết quả hòa, và chủ tịch Bdale Garbee bỏ lá phiếu quyết định cho systemd. Vài ngày sau, Ubuntu thông báo sẽ theo Debian thay vì tiếp tục dùng Upstart. Một nhóm developer của Debian đã fork distribution này thành Devuan vào tháng 11 năm 2014 và phát hành Devuan 1.0 vào tháng 5 năm 2017.

Những phản đối, được trình bày công bằng

Phạm vi. Một project hiện phát hành PID 1, daemon ghi log, quản lý login session, device manager, daemon cấu hình network, DNS (domain name system) resolver, NTP (network time protocol) client, container runner và boot loader. Lập luận phòng vệ thường gặp rằng đây là các binary riêng và bạn không bắt buộc phải cài chúng là đúng, nhưng không giải quyết được phản đối này. Khi một desktop cần logind và logind được tách khỏi cây của systemd, lựa chọn không còn hoàn toàn tự do. Đó là ý nghĩa của coupling trong lập luận, và điều đó đã xảy ra.

Binary journal. journald ghi log ở định dạng binary có index thay vì plain text. Bạn nhận được những thứ mà text không cung cấp: lọc theo unit và priority, các field có cấu trúc, cùng metadata mà chương trình gửi không thể giả mạo vì chính journald ghi lại unit và cgroup. journalctl -u nginx -p err --since "-1h" thay cho grep bằng một regular expression theo ngày. Chi phí cũng là có thật. Trên máy không boot được, bạn không thể đọc log bằng less từ rescue shell. Thay vào đó, trỏ journalctl đến disk đã mount:

sudo journalctl --directory /mnt/var/log/journal --boot -1 --priority err

Có một bẫy thứ hai mà người dùng thường chỉ gặp một lần. journald giữ log trong /run/log/journal, tức memory, trừ khi tồn tại /var/log/journal. Trên máy không có nó, journalctl -b -1 không có gì để hiển thị sau reboot, đúng vào lúc bạn cần log nhất. Hãy kiểm tra và sửa:

journalctl --disk-usage
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald

journalctl --disk-usage hiện sẽ báo các journal đã archive trong /var/log/journal. Nếu muốn có cả plain text, đặt ForwardToSyslog=yes trong /etc/systemd/journald.conf và giữ rsyslog đã cài.

Khả năng debug boot. Khi một unit bị treo, console chỉ hiển thị một dòng rồi không có gì khác:

[  *** ] A start job is running for Wait for Network to be Configured (1min 32s / no limit)

Các tool để tìm hiểu sâu hơn vẫn có: systemctl list-jobs trong lúc unit đang bị treo, systemd-analyze blame và systemd-analyze critical-chain sau đó, cùng systemd.log_level=debug trên kernel command line. Cách trình bày công bằng cho phản đối này là: bất kỳ ai biết sh đều có thể đọc init script từ đầu đến cuối, còn khi một unit bị treo, bạn phải biết nên dùng lệnh nào trong số hàng chục lệnh. Đây là một chi phí thực sự. Mỗi administrator chỉ trả chi phí này một lần, nhưng rất nhiều administrator đã phải trả cùng lúc.

Một default thay đổi cho tất cả mọi người. systemd 230 vào năm 2016 đã thay đổi default của logind để các user process còn sót lại bị kill khi logout. Các session tmux và screen chạy tách khỏi terminal đã bị kết thúc khi session khởi tạo chúng kết thúc. Các distribution phát hành KillUserProcesses=no trong /etc/systemd/logind.conf, và cách được hỗ trợ là loginctl enable-linger <user>. Một default trong một project đã thay đổi thói quen mà hàng triệu người dựa vào. Đó là ý nghĩa thực tế của việc có “quá nhiều userland ở cùng một chỗ”.

Một dependency mặc định là một bề mặt tấn công. Vào tháng 3 năm 2024, backdoor trong xz-utils nhắm vào sshd trên Debian và Ubuntu. OpenSSH upstream không link với libsystemd. Các distribution đó patch sshd để sshd có thể báo trạng thái sẵn sàng cho systemd, và libsystemd kéo liblzma vào, nơi backdoor tồn tại. Bản thân readiness protocol chỉ là một datagram được gửi đến socket có tên trong $NOTIFY_SOCKET, nên chưa từng có library nào là bắt buộc cho việc này. Phản hồi của systemd là load các compression library bằng dlopen, để chúng không còn được link mặc định. Một nhóm bug liên quan cũng cho thấy cùng mô hình: vào năm 2017, giá trị User= bắt đầu bằng một chữ số bị xem là không hợp lệ và unit chạy với quyền root thay vì fail, khiến một typo trở thành privilege escalation. Các version sau từ chối start unit.

Lịch sử ngay trong prompt systemctl của hệ thống

Mỗi vấn đề ở trên giờ đã trở thành một directive trong một file mà bạn có thể đọc.

  • Boot tuần tự trở thành After= và Wants=, còn systemd-analyze critical-chain cho biết chính xác thành phần nào đã giữ boot của bạn.
  • Readiness trở thành Type=notify. Service ghi READY=1 vào $NOTIFY_SOCKET khi có thể phục vụ request. Type=forking cùng PIDFile= vẫn tồn tại cho các daemon cũ, và đây là type sẽ fail với start operation timed out. Terminating. nếu PID file không bao giờ xuất hiện. Chọn sai type là lý do unit báo active trong khi daemon mà nó khởi động đã thoát, vì vậy bạn nên biết Type= nào phù hợp với cách daemon thực sự khởi động trước khi viết dòng đó.
  • Supervision trở thành cgroup, nên Restart=on-failure cùng RestartSec= thay thế wrapper script, còn StartLimitBurst= ngăn crash loop chạy vô hạn.
  • inetd trở thành một unit .socket nằm cạnh unit .service.
  • ulimit trở thành MemoryMax=, CPUQuota= và TasksMax=.
  • Dòng su - appuser -c trong init script trở thành User=, NoNewPrivileges=yes và ProtectSystem=strict, vì vậy chạy service bằng user không có đặc quyền là cấu trúc mặc định của một unit thay vì phần việc phải làm thêm.
[Unit]
Description=Example API
Wants=network-online.target
After=network-online.target postgresql.service
Requires=postgresql.service

[Service]
Type=notify
ExecStart=/usr/local/bin/exampled
Restart=on-failure
RestartSec=2
MemoryMax=512M
CPUQuota=50%
TasksMax=128
User=exampled
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
StateDirectory=exampled

[Install]
WantedBy=multi-user.target

Có một dòng trong file này mà ai cũng mắc lỗi một lần. Requires=postgresql.service là requirement, không phải thứ tự khởi động: nó nói unit của bạn sẽ fail nếu Postgres fail, chứ không nói phải khởi động Postgres trước. Nếu không có After=postgresql.service, cả hai sẽ khởi động cùng lúc và service của bạn sẽ kết nối đến một port mà chưa có process nào listening. Hai directive này được tách riêng có chủ ý, vì đôi khi bạn cần một directive mà không cần directive còn lại. ProtectSystem=strict mount file system ở chế độ read-only cho service này. Vì vậy mới có StateDirectory=: nó cấp cho service một path có thể ghi dưới /var/lib.

Nơi dễ thấy nhất sự thay đổi từ năm 2005 trên một server năm 2026 là SSH trên Ubuntu 24.04, bản này cung cấp systemd 255 tính đến tháng 8 năm 2026. ssh.service mặc định được socket activate: ssh.socket giữ listening socket, còn sshd khởi động khi có connection đến. Vì vậy Port 2222 trong /etc/ssh/sshd_config không có tác dụng, vì sshd không phải process đã mở port. Thay đổi này phải được đặt trong socket unit.

sudo systemctl edit ssh.socket
[Socket]
ListenStream=
ListenStream=2222

ListenStream= rỗng sẽ xóa giá trị được kế thừa từ unit do package cung cấp. Nếu bỏ dòng này, bạn sẽ có cả hai port, vì systemd nối thêm vào list thay vì thay thế list. Sau đó apply thay đổi và kiểm tra, đồng thời giữ nguyên một SSH session thứ hai trong suốt quá trình:

sudo systemctl daemon-reload
sudo systemctl restart ssh.socket
sudo ss -lntp | grep 2222

ss phải liệt kê một socket trên port 2222 do systemd sở hữu, không phải sshd. Đó là thiết kế của launchd, sau 20 năm, trên VPS của bạn. Nếu muốn hành vi cũ, sudo systemctl disable --now ssh.socket rồi sudo systemctl enable --now ssh.service sẽ cho bạn một sshd chạy lâu dài và đọc Port từ config riêng của nó lần nữa.

Bạn gặp những chi tiết nào còn tùy thuộc vào release đang chạy, vì vậy nên biết khác biệt giữa Ubuntu LTS và interim release trước khi lập kế hoạch upgrade. Trên nhiều máy, việc unit file giống hệt nhau ở mọi nơi là lý do quản lý nhiều server từ một nơi hiện là bài toán configuration thay vì bài toán shell scripting. Khi tự viết unit, cặp service và timer sẽ thực hiện công việc mà năm 2009 bạn phải chia thành một init script và một dòng cron.

FAQ

Vì sao các bản phân phối Linux thay SysV init bằng systemd?

Có 2 lý do kỹ thuật và 1 lý do bảo trì. SysV init sắp xếp service theo tên file. Đây là thứ tự vị trí, không phải dependency. Nó cũng mất dấu daemon đã fork khỏi process cha. Vì vậy, PID file cũ có thể khiến nhầm process bị kill. systemd giải quyết việc sắp xếp thứ tự bằng socket activation và các chỉ thị dependency. Nó giải quyết việc theo dõi process bằng control group. Lý do bảo trì quyết định tốc độ chuyển đổi: một unit file hoạt động trên mọi bản phân phối. Vì vậy, các dự án upstream chỉ cần phát hành một file .service, còn maintainer của bản phân phối không phải viết shell script riêng cho từng package. Fedora 15 chuyển sang systemd vào tháng 5 năm 2011. Ubuntu 15.04 là bản lớn cuối cùng chưa chuyển đổi, vào tháng 4 năm 2015.

systemd có phải là một binary khổng lồ không?

Không. Source tree build nhiều chương trình riêng biệt. PID 1 là /usr/lib/systemd/systemd. journald, logind và udevd là các process riêng, mỗi process có binary riêng. Chạy ls /usr/lib/systemd/ để xem chúng trên máy của bạn. Điểm bị phê bình còn tồn tại liên quan đến việc ghép phiên bản release, không phải kích thước binary: các chương trình này được release cùng nhau và dùng chung các interface private. Vì vậy, các bản phân phối thường lấy chúng theo cả bộ. Phần mềm như GNOME cũng dần yêu cầu riêng logind.

Tôi vẫn có thể chạy Linux mà không dùng systemd không?

Có. Devuan phát hành cùng sysvinit, Gentoo mặc định dùng OpenRC, Void dùng runit, Alpine dùng busybox init cùng OpenRC, còn Slackware vẫn giữ các script theo kiểu BSD. Chi phí là công việc tương thích. Phần mềm desktop yêu cầu logind cần elogind. Đây là logind của systemd được duy trì dưới dạng package độc lập. Ngày càng nhiều phần mềm server chỉ phát hành file .service. Vì vậy, bạn phải tự viết và duy trì startup script.

Vì sao journal dùng định dạng binary thay vì file text thông thường?

Vì journald lưu các field có cấu trúc cùng một index. Nhờ đó, bạn có thể filter theo unit và priority, đồng thời có metadata mà chương trình gửi log không thể giả mạo. journald tự ghi nhận unit, cgroup và UID thật thay vì tin vào nội dung của dòng log. Đổi lại, bạn cần journalctl để đọc journal, kể cả từ rescue system. Khi đó, bạn trỏ công cụ này đến disk đã mount bằng journalctl --directory /mnt/var/log/journal. Nếu muốn có cả text log, hãy đặt ForwardToSyslog=yes trong /etc/systemd/journald.conf.

Điều gì thay cho việc chỉnh sửa script /etc/init.d của tôi?

Đó là các file drop-in. Không chỉnh sửa unit trong /usr/lib/systemd/system/, vì package upgrade sẽ ghi đè file này. Chạy sudo systemctl edit nginx.service, systemd sẽ tạo /etc/systemd/system/nginx.service.d/override.conf. File này được merge lên unit do package cung cấp. systemctl cat nginx.service hiển thị kết quả sau khi merge. systemd-delta liệt kê mọi override trên máy. Sau mỗi lần chỉnh sửa thủ công, hãy chạy sudo systemctl daemon-reload. Nếu không, lệnh tiếp theo sẽ in Warning: The unit file, source configuration file or drop-ins of nginx.service changed on disk.

#systemd#linux#init#sysvinit#history