Đáng ngạc nhiên, sau 5 năm hoặc lâu hơn của WSL, dường như không có câu hỏi "Systemd" có mục đích chung, hay ở đây trên Ask Ubuntu. Vì vậy, đây có vẻ là một cách tốt để sử dụng cho mục đích đó.
Vấn đề
Nói chung, khi bạn nhìn thấy một trong hai trong hai thông báo sau:
Hệ thống chưa được khởi động với systemd là hệ thống init (PID 1). Không thể hoạt động.
Không thể kết nối với xe buýt: Máy chủ không hoạt động
Sau đó, nó thường là cùng một nguyên nhân gốc rễ. Trong trường hợp hệ thống
và cố gắng bắt đầu ssh
, bạn đang nhìn thấy cả hai.
Vấn đề cốt lõi, như đã đề cập trong các nhận xét, là WSL không sử dụng Systemd, ngay cả trong các bản phân phối có mặc định. Thay vào đó, WSL hiện đang sử dụng /trong đó
xử lý dưới dạng PID 1, thực hiện một số tác vụ dành riêng cho WSL mà tôi đã đề cập trong câu trả lời này (vì vậy tôi sẽ không lặp lại chúng ở đây).
Và mặc dù WSL là (IMHO) một cách tuyệt vời để có Linux CLI đầy đủ tính năng trong Windows (và gần đây, thậm chí cả GUI), nhưng việc thiếu Systemd có xu hướng khiến mọi thứ trở nên khó khăn hơn trong các bản phân phối. chờ đợi nó ở đó. May mắn thay, Ubuntu nhìn chung khá tốt về khả năng xử lý mà không cần Systemd.
Cách xử lý khi thiếu Systemd
Và bất kể, Systemd về cốt lõi chỉ là một "cách hoàn thành nhiệm vụ hệ thống" (có thể là quá đơn giản hóa). Có (thường? Luôn luôn?) Một cách để thực hiện cùng một tác vụ mà không cần Systemd và thường là nhiều cách.
Phương án 1: "Con đường cũ"
Trong Ubuntu trên WSL, nhiều dịch vụ hệ thống phổ biến vẫn còn "cũ" init.d
tập lệnh có sẵn để được sử dụng thay cho hệ thống
với các đơn vị Systemd. Bạn có thể thấy những điều này bằng cách sử dụng ls /etc/init.d/
.
Vì vậy, ví dụ, bạn có thể bắt đầu ssh
với dịch vụ sudo ssh bắt đầu
, và nó sẽ chạy /etc/init.d/ssh
kịch bản với bắt đầu
tranh luận.
Ngay cả một số gói không mặc định như MySql/MariaDB sẽ cài đặt cả tệp đơn vị Systemd và người già init.d
tập lệnh, vì vậy bạn vẫn có thể sử dụng dịch vụ
lệnh cho họ là tốt.
Phương án 2: "Cách 'thủ công'"
Nhưng một số dịch vụ không có init-script tương đương, đặc biệt là trên các bản phân phối khác. Để đơn giản, giả sử rằng ssh
init.d
kịch bản không phải có sẵn.
Trong trường hợp này, "câu trả lời" là tìm hiểu xem các tệp đơn vị Systemd đang làm gì và cố gắng sao chép thủ công. Điều này có thể rất khác nhau về độ phức tạp. Nhưng tôi sẽ bắt đầu bằng việc xem tệp đơn vị Systemd mà bạn đang cố chạy:
ít hơn /lib/systemd/system/ssh.service
# cắt tỉa
[Dịch vụ]
Tệp môi trường=-/etc/default/ssh
ExecStartPre=/usr/sbin/sshd -t
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
RuntimeDirectory=sshd
RuntimeDirectoryMode=0755
Tôi đã lược bớt một số dòng ít liên quan hơn để hiểu hành vi của nó, nhưng bạn có thể người đàn ông systemd.exec
, người đàn ông systemd.service
, và những người khác để xem những gì hầu hết các tùy chọn làm.
Trong trường hợp này, khi bạn Sudo systemctl bắt đầu ssh
, nó:
- Đọc các biến môi trường (các
$SSHD_OPTS
) từ /etc/mặc định/ssh
- Kiểm tra cấu hình, thoát nếu có lỗi
- Đảm bảo RuntimeDirectory tồn tại với các quyền được chỉ định. Điều này có nghĩa là
/run/sshd
(từ người đàn ông systemd.exec
). Thao tác này cũng xóa thư mục thời gian chạy khi bạn dừng dịch vụ.
- chạy
/usr/sbin/sshd
với các tùy chọn
Vì vậy, nếu bạn không có bất kỳ cấu hình dựa trên môi trường nào, bạn có thể thiết lập một tập lệnh để:
- Đảm bảo thư mục thời gian chạy tồn tại. Lưu ý rằng, vì nó nằm trong
/chạy
, mà là một tmpfs
mount, nó sẽ bị xóa sau mỗi lần khởi động lại phiên bản WSL.
- Đặt quyền thành
0755
- Bắt đầu
/usr/sbin/sshd
như gốc
... Và bạn sẽ làm điều tương tự thủ công không có Systemd.
Một lần nữa, đây có lẽ là ví dụ đơn giản nhất. Bạn có thể có nhiều việc phải giải quyết cho các nhiệm vụ phức tạp hơn.
Tùy chọn 3: Chạy Systemd dưới dạng PID 1 trong vùng chứa/vùng chứa tên PID
Cuối cùng, nó là khả thi để có được Systemd chạy trong WSL. Đây là một chủ đề khá nâng cao, mặc dù có nhiều tập lệnh và dự án cố gắng đơn giản hóa nó. Mặc dù vậy, khuyến nghị cá nhân của tôi là đảm bảo rằng bạn hiểu những gì đang diễn ra đằng sau hậu trường nếu bạn sử dụng một trong những kỹ thuật này.
Hãy bắt đầu với một số dự án phổ biến hơn để kích hoạt Systemd trong WSL:
Cá nhân tôi chưa chạy bất kỳ ứng dụng nào trong số chúng, nhưng tất cả đều là mã nguồn mở và tôi đã quét mã nguồn để so sánh các kỹ thuật. Về cốt lõi, mỗi cái tạo một không gian tên hoặc vùng chứa mới trong đó Systemd có thể chạy dưới dạng PID 1.
Bạn có thể thấy điều này trong hành động bằng cách làm theo các bước:
Chạy:
sudo -b unshare --pid --fork --mount-proc /lib/systemd/systemd --system-unit=basic.target
Điều này bắt đầu Systemd trong một không gian tên mới với ánh xạ PID của chính nó. Bên trong không gian tên đó, Systemd sẽ là PID1 (như nó phải hoạt động) và sở hữu tất cả các quy trình khác. Tuy nhiên, ánh xạ PID "thực" vẫn tồn tại bên ngoài không gian tên đó.
Lưu ý rằng đây là dòng lệnh "tối thiểu" để khởi động Systemd. Nó sẽ không có hỗ trợ cho, ít nhất là:
- Windows Interop (khả năng chạy Windows
.exe
)
- Windows PATH (không cần thiết nếu không có Windows Interop)
Các tập lệnh và dự án được liệt kê ở trên thực hiện thêm công việc để những thứ này hoạt động tốt.
Đợi vài giây để Systemd khởi động, sau đó:
sudo -E nsenter --all -t $(pgrep -xo systemd) runuser -P -l $USER -c "exec $SHELL"
Điều này đi vào không gian tên và bây giờ bạn có thể sử dụng ps -efH
để thấy rằng hệ thống
đang chạy dưới dạng PID 1 trong không gian tên đó.
Tại thời điểm này, bạn sẽ có thể chạy hệ thống
.
Và sau khi tự chứng minh rằng điều đó là có thể, tôi khuyên bạn nên thoát hoàn toàn phiên bản WSL, sau đó thực hiện wsl --terminate <distro>
trên đó. Nếu không, bạn sẽ có một số thứ bị "hỏng" cho đến khi bạn làm. Chúng có thể được "sửa", nhưng điều đó nằm ngoài phạm vi của bất kỳ câu hỏi nào về Đặt câu hỏi cho Ubuntu ;-). Khuyến nghị của tôi là tham khảo các dự án ở trên để xem cách họ xử lý.