น่าแปลกที่หลังจาก 5 ปีหรือมากกว่านั้นของ WSL ดูเหมือนจะไม่มีคำถาม "ระบบ" ที่ดีและมีจุดประสงค์ทั่วไปที่นี่ในถามอูบุนตู ดังนั้นสิ่งนี้จึงดูดีที่จะใช้เพื่อจุดประสงค์นั้น
ปัญหา
โดยทั่วไปเมื่อคุณเห็น ทั้ง จากสองข้อความต่อไปนี้:
ระบบไม่ได้บู๊ตด้วย systemd เป็นระบบเริ่มต้น (PID 1) ไม่สามารถใช้งานได้
ไม่สามารถเชื่อมต่อกับบัส: โฮสต์ไม่ทำงาน
โดยทั่วไปแล้วจะเป็นสาเหตุเดียวกัน ในกรณีของ systemctl
และพยายามที่จะเริ่มต้น จุ๊ๆ
คุณจะเห็นทั้งสองอย่าง
ปัญหาหลักตามที่กล่าวไว้ในความคิดเห็นคือ WSL ไม่ได้ใช้ Systemd แม้ในการแจกจ่ายที่เป็นค่าเริ่มต้น ปัจจุบัน WSL ใช้ของตัวเองแทน /ในนั้น
ประมวลผลเป็น PID 1 ซึ่งทำงานเฉพาะ WSL บางอย่างที่ฉันพูดถึง คำตอบนี้ (ดังนั้นฉันจะไม่ทำซ้ำที่นี่)
และในขณะที่ WSL คือ (IMHO) วิธีที่ยอดเยี่ยมในการมี Linux CLI ที่มีคุณสมบัติครบถ้วนใน Windows (และเมื่อเร็ว ๆ นี้แม้แต่ GUI) การขาด Systemd มักจะทำให้สิ่งต่าง ๆ ยากขึ้นในการแจกจ่าย คาดหวัง มันจะอยู่ที่นั่น โชคดีที่อูบุนตูโดยรวมค่อนข้างดีเกี่ยวกับความสามารถในการรับมือโดยไม่ต้องใช้ Systemd
วิธีจัดการกับการขาด Systemd
และไม่คำนึงว่า Systemd ที่เป็นแกนหลักเป็นเพียง "วิธีการทำงานของระบบให้สำเร็จ" มีวิธี (ปกติหรือไม่ เสมอ?) ในการทำงานเดียวกันโดยไม่มี Systemd และมักมีมากกว่าหนึ่งวิธี
ตัวเลือกที่ 1: "ทางเก่า"
ใน Ubuntu บน WSL บริการระบบทั่วไปจำนวนมากยังคงมี "เก่า" init.d
สคริปต์ที่ใช้แทนได้ systemctl
ด้วยหน่วย Systemd คุณสามารถดูสิ่งเหล่านี้ได้โดยใช้ ls /etc/init.d/
.
ตัวอย่างเช่น คุณสามารถเริ่มต้น จุ๊ๆ
กับ sudo บริการ ssh เริ่มต้น
และมันจะเรียกใช้ /etc/init.d/ssh
สคริปต์กับ เริ่ม
การโต้แย้ง.
แม้แต่แพ็คเกจที่ไม่ใช่ค่าเริ่มต้นเช่น MySql/MariaDB ก็จะติดตั้งทั้งไฟล์ยูนิต Systemd และ เก่า init.d
สคริปต์ ดังนั้นคุณยังคงสามารถใช้ไฟล์ บริการ
คำสั่งสำหรับพวกเขาเช่นกัน
ตัวเลือกที่ 2: "วิธี 'ด้วยตนเอง'"
แต่บริการบางอย่างไม่มี init-script ที่เทียบเท่า โดยเฉพาะอย่างยิ่งในการแจกจ่ายอื่นๆ เพื่อความง่าย สมมติว่า จุ๊ๆ
init.d
สคริปต์ ไม่ใช่ มีอยู่.
ในกรณีนี้ "คำตอบ" คือการค้นหาว่าไฟล์หน่วย Systemd กำลังทำอะไรและพยายามทำซ้ำด้วยตนเอง สิ่งนี้อาจแตกต่างกันไปตามความซับซ้อน แต่ฉันจะเริ่มต้นด้วยการดูไฟล์หน่วย Systemd ที่คุณพยายามเรียกใช้:
น้อยกว่า /lib/systemd/system/ssh.service
#ตัดแต่ง
[บริการ]
EnvironmentFile=-/etc/default/ssh
ExecStartPre=/usr/sbin/sshd -t
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
RuntimeDirectory=sshd
RuntimeDirectoryMode=0755
ฉันได้ตัดทอนบรรทัดที่เกี่ยวข้องน้อยกว่าบางส่วนออกเพื่อให้เข้าใจพฤติกรรมของมัน แต่คุณทำได้ คน systemd.exec
, คน systemd.service
และอื่น ๆ เพื่อดูว่าตัวเลือกส่วนใหญ่ทำอะไรได้บ้าง
ในกรณีนี้ เมื่อคุณ sudo systemctl เริ่ม ssh
, มัน:
- อ่านตัวแปรสภาพแวดล้อม (the
$SSHD_OPTS
) จาก /etc/default/ssh
- ทดสอบการกำหนดค่า ออกหากเกิดข้อผิดพลาด
- ตรวจสอบให้แน่ใจว่า RuntimeDirectory มีอยู่โดยมีสิทธิ์ที่ระบุ สิ่งนี้แปลว่า
/รัน/sshd
(จาก คน systemd.exec
). นอกจากนี้ยังลบไดเร็กทอรีรันไทม์เมื่อคุณหยุดบริการ
- วิ่ง
/usr/sbin/sshd
พร้อมตัวเลือก
ดังนั้น หากคุณไม่มีการกำหนดค่าตามสภาพแวดล้อม คุณสามารถตั้งค่าสคริปต์เพื่อ:
- ตรวจสอบให้แน่ใจว่ามีไดเร็กทอรีรันไทม์อยู่ โปรดทราบว่าเนื่องจากอยู่ใน
/วิ่ง
ซึ่งก็คือก tmpfs
เมานต์จะถูกลบหลังจากรีสตาร์ทอินสแตนซ์ WSL ทุกครั้ง
- กำหนดสิทธิ์เป็น
0755
- เริ่ม
/usr/sbin/sshd
เป็นราก
... และคุณก็คงทำแบบเดียวกัน ด้วยตนเอง ไม่มีระบบ
นี่อาจเป็นตัวอย่างที่ง่ายที่สุดอีกครั้ง คุณอาจต้องทำงานที่ซับซ้อนมากขึ้น
ตัวเลือกที่ 3: เรียกใช้ Systemd เป็น PID 1 ในเนมสเปซ/คอนเทนเนอร์ PID
สุดท้ายก็คือ เป็นไปได้ เพื่อให้ Systemd ทำงานภายใต้ WSL นี่เป็นหัวข้อขั้นสูงแม้ว่าจะมีหลายสคริปต์และโครงการที่พยายามทำให้ง่ายขึ้น ถึงกระนั้นก็ตาม คำแนะนำส่วนตัวของฉันคือเพื่อให้แน่ใจว่าคุณเข้าใจสิ่งที่เกิดขึ้นเบื้องหลัง หากคุณใช้หนึ่งในเทคนิคเหล่านี้
เรามาเริ่มกันที่โปรเจ็กต์ยอดนิยมเพื่อเปิดใช้งาน Systemd ใน WSL:
ฉันไม่ได้เรียกใช้สิ่งเหล่านี้เป็นการส่วนตัว แต่ทั้งหมดเป็นโอเพ่นซอร์สและฉันได้สแกนซอร์สเพื่อเปรียบเทียบเทคนิค ที่แกนหลัก แต่ละรายการจะสร้างเนมสเปซหรือคอนเทนเนอร์ใหม่ที่ Systemd สามารถเรียกใช้เป็น PID 1
คุณสามารถดูการทำงานได้โดยทำตามขั้นตอน:
วิ่ง:
sudo -b unshare --pid --fork --mount-proc /lib/systemd/systemd --system-unit=basic.target
สิ่งนี้เริ่ม Systemd ในเนมสเปซใหม่ด้วยการแมป PID ของตัวเอง ภายในเนมสเปซนั้น Systemd จะเป็น PID1 (ตามที่จำเป็นเพื่อให้ทำงานได้) และเป็นเจ้าของกระบวนการอื่นๆ ทั้งหมด อย่างไรก็ตาม การแมป PID "จริง" ยังคงมีอยู่นอกเนมสเปซนั้น
โปรดทราบว่านี่เป็นบรรทัดคำสั่ง "ขั้นต่ำสุด" สำหรับการเริ่มต้น Systemd จะไม่รองรับอย่างน้อย:
- Windows Interop (ความสามารถในการเรียกใช้ Windows
.exe
)
- Windows PATH (ซึ่งไม่จำเป็นหากไม่มี Windows Interop)
สคริปต์และโปรเจ็กต์ที่ระบุไว้ด้านบนทำงานพิเศษเพื่อให้สิ่งเหล่านี้ทำงานได้ดี
รอสักครู่เพื่อให้ Systemd เริ่มทำงาน จากนั้น:
sudo -E nsenter --all -t $(pgrep -xo systemd) runuser -P -l $USER -c "exec $SHELL"
สิ่งนี้เข้าสู่เนมสเปซและตอนนี้คุณสามารถใช้งานได้ ps -efH
เพื่อดูว่า ระบบ
กำลังทำงานเป็น PID 1 ในเนมสเปซนั้น
ณ จุดนี้ คุณควรจะวิ่งได้แล้ว systemctl
.
และหลังจากพิสูจน์ด้วยตัวคุณเองว่าเป็นไปได้ ฉันขอแนะนำให้ออกจากอินสแตนซ์ WSL โดยสิ้นเชิง แล้วจึงดำเนินการ wsl --terminate <distro>
บนมัน มิฉะนั้นคุณจะมีบางอย่าง "หัก" จนกว่าคุณจะทำ พวกเขาสามารถ "แก้ไข" ได้ แต่นั่นอยู่นอกเหนือขอบเขตของคำถามใด ๆ ของ Ubuntu ;-) คำแนะนำของฉันคือการอ้างถึงโครงการด้านบนเพื่อดูว่าพวกเขาจัดการอย่างไร