ตรวจจับระบบ init โดยใช้เชลล์


90

สิ่งนี้อาจมีอะไรเพิ่มเติมเกี่ยวกับการตรวจจับระบบปฏิบัติการ แต่ฉันต้องการระบบเริ่มต้นที่ใช้อยู่ในระบบเป็นพิเศษ

Fedora 15 และ Ubuntu ตอนนี้ใช้ systemd, Ubuntu เคยใช้ Upstart (เริ่มต้นนานจนถึง 15.04), ในขณะที่คนอื่นใช้รูปแบบของ System V

ฉันมีแอปพลิเคชันที่ฉันเขียนเพื่อเป็นภูตข้ามแพลตฟอร์ม สคริปต์ init กำลังถูกสร้างแบบไดนามิกขึ้นอยู่กับพารามิเตอร์ที่สามารถส่งผ่านไปยังการกำหนดค่า

สิ่งที่ฉันต้องการทำคือสร้างสคริปต์สำหรับระบบเริ่มต้นเฉพาะที่ใช้ วิธีนี้สคริปต์การติดตั้งสามารถรันได้อย่างสมเหตุสมผลโดยไม่มีพารามิเตอร์เนื่องจากรูทและ daemon สามารถ "ติดตั้ง" โดยอัตโนมัติ

นี่คือสิ่งที่ฉันเกิดขึ้น:

  • ค้นหา systemd, พุ่งพรวด, ฯลฯ ใน / bin
  • เปรียบเทียบ / proc / 1 / comm กับ systemd, พุ่งพรวด, ฯลฯ
  • ถามผู้ใช้

สิ่งที่จะเป็นวิธีที่ข้าม / แพลตฟอร์มที่ดีที่สุดในการทำเช่นนี้?

ประเภทที่เกี่ยวข้องฉันสามารถพึ่งพาการทุบตีเป็นส่วนใหญ่ของ * ระวังหรือมันขึ้นอยู่กับการกระจาย / ระบบปฏิบัติการ?

แพลตฟอร์มเป้าหมาย:

  • Mac OS
  • Linux (ดิสทริบิวชันทั้งหมด)
  • BSD (ทุกรุ่น)
  • Solaris, Minix และอื่น ๆ * ระวัง

1
เพียงเพิ่มสองเซ็นต์ของฉันทุบตีไม่ได้ติดตั้งโดยค่าเริ่มต้นใน FreeBSD
Chinmay Kanchi

@tjameson คุณหาวิธีที่ตรงกว่านี้ไหม? ฉันกำลังมองหาสิ่งเดียวกัน แต่คำตอบที่นี่เป็นเพียงทิศทางไม่ใช่คำตอบโดยตรง โดยเฉพาะอย่างยิ่ง 1) ตำแหน่งสคริปต์ที่ต้องการค้นหาและ 2) การตรวจจับระบบ init ที่มีผลบังคับใช้ในกรณีที่มีการติดตั้งหลายรายการ (ตอบกลับทุบตีโดยตรง)
n611x007

3
@naxa - คำตอบสั้น ๆ คำตอบยาวคุณสามารถทำได้ค่อนข้างไกลด้วยps -p 1 -o command(พิมพ์เส้นทางสู่ปัจจุบันinit) บน Arch Linux และ Fedora (IIRC) มันเป็น symlink ไปยังsystemdไบนารี (อาจเหมือนกันในทุกsystemdระบบ) เมื่อวันที่upstart, init --helpจะพิมพ์ข้อมูลการใช้งานและในกล่องของฉันupstartเป็นที่กล่าวถึงที่จะกล่าวว่าผู้ที่จะส่งอีเมล บน FreeBSD (sysV) สิ่งนี้จะส่งคืนข้อผิดพลาด อาจมีเงื่อนงำที่คล้ายกันในระบบอื่น ๆ แต่เมื่อถามคำถามนี้ฉันตัดสินใจที่จะสร้างพวกมันสำหรับทุกแพลตฟอร์มและสร้างแพ็คเกจแยกต่างหากสำหรับแต่ละระบบ
beatgammit

ขอบคุณข้อมูลที่ดี! กระโดดจากสิ่งที่ฉันได้เรียนรู้ว่าsudo lsof -a -p 1 -d txtอาจให้ผลลัพธ์ที่แม่นยำยิ่งขึ้น psอาจพิมพ์ชื่อโดยพลการในขณะที่lsofคุณจะได้รับเส้นทางปฏิบัติการจริง (ดูคำถามของฉันunix.stackexchange.com/questions/102453/… )
n611x007

1
ไม่มีคำตอบหรือความคิดเห็นในคำถามที่เชื่อมโยงซึ่งเกี่ยวข้องกับการทุบตี โซลูชันควรใช้กับกรณีของคุณเช่นกัน
Marco

คำตอบ:


30

สำหรับคำถามที่สองคำตอบคือไม่มีและคุณควรจะมีลักษณะที่ทรัพยากรสำหรับการเขียนโปรแกรมเปลือกแบบพกพา

สำหรับส่วนแรก - ก่อนอื่นคุณต้องระวังอย่างแน่นอน ผมว่าดำเนินการทดสอบหลายอย่างเพื่อให้แน่ใจว่า - เพราะความจริงที่ว่าคนที่ไม่ได้ systemd. (อดีต) initติดตั้งไม่ได้หมายความว่ามันจะถูกนำมาใช้จริงเป็นค่าเริ่มต้น นอกจากนี้การดู/proc/1/commอาจทำให้เข้าใจผิดเนื่องจากการติดตั้งโปรแกรมเริ่มต้นต่างๆสามารถสร้าง/sbin/initลิงก์เชื่อมโยงหรือโดยอัตโนมัติเป็นเวอร์ชันหลักของโปรแกรมหลักได้

บางทีสิ่งที่มีประโยชน์ที่สุดคือดูประเภทของสคริปต์เริ่มต้น - เพราะสิ่งเหล่านั้นคือสิ่งที่คุณจะสร้างขึ้นมาจริงไม่ว่าจะทำงานอะไรก็ตาม

ในฐานะที่เป็นหมายเหตุด้านข้างคุณอาจจะดูOpenRCซึ่งมีจุดมุ่งหมายเพื่อให้โครงสร้างของสคริปต์เริ่มต้นที่เข้ากันได้กับทั้งระบบ Linux และ BSD


2
คุณหมายถึงอะไรโดย "ดูที่ประเภทสคริปต์เริ่มต้น" บ่อยครั้งที่ระบบ init ที่แตกต่างกันของพวกเขาวางสคริปต์ / ไฟล์ที่ไหนสักแห่งนอกเหนือ/etc/initเช่น systemd /etc/systemdทำให้พวกเขาใน ถ้าฉันจะให้สคริปต์ของฉันคลุ้มคลั่งมันอาจใช้เวลาสักครู่ โอ้และขอบคุณสำหรับลิงค์ BTW สำหรับการเขียนโปรแกรมเชลล์แบบพกพา
beatgammit

1
ฉันอยากจะบอกว่าการติดตั้งแอปพลิเคชั่นเริ่มต้นบางอย่างสามารถปรับเปลี่ยนเพื่อใช้ประโยชน์จากประเภทและตำแหน่งของสคริปต์เริ่มต้น (เช่น/etc/rc.d/หรือ/etc/init.d/) และคุณควรปรับโปรแกรมของคุณอย่างเหมาะสมในเวลาติดตั้งเพื่อใช้โครงสร้างที่ใช้ในระบบที่กำหนด
rozcietrzewiacz

2
คุณกำลังบอกว่าไม่มีวิธีที่เชื่อถือได้ในการตรวจสอบระบบ init โดยทางโปรแกรมหรือไม่ การที่ผู้ใช้ผ่านพารามิเตอร์นั้นปลอดภัยกว่า แต่ถ้าผู้ใช้ไม่ผ่านอะไรสิ่งใดจะเป็นวิธีที่ดีที่สุดในการเดา
beatgammit

ฉันไม่รู้ว่าอะไรจะเป็นวิธีที่ดีที่สุดสำหรับโปรแกรมของคุณ - ทุกอย่างขึ้นอยู่กับว่าโปรแกรมใดที่โปรแกรมจะจบการทำงาน ฉันไม่ได้ใช้การแจกแจงมากเกินไป แต่ฉันพยายามแบ่งปันข้อสังเกตของฉันเพื่อช่วยคุณ มันเป็นสคริปต์ที่ยากที่คุณจะลองและฉันพยายามที่จะให้คุณดูในสนาม - คุณจะต้องตอบคำถามสุดท้ายด้วยตัวเองหรือรอคำแนะนำเพิ่มเติม
rozcietrzewiacz

เยี่ยมขอบคุณสำหรับความช่วยเหลือของคุณ คุณได้ชี้ให้ฉันในทิศทางที่ถูกต้องแน่นอน
beatgammit

58

ฉันก้าวเข้าสู่ปัญหานี้ด้วยตัวเองและตัดสินใจที่จะทำการทดสอบ ฉันเห็นด้วยอย่างยิ่งกับคำตอบที่ควรจัดแพคเกจสำหรับแต่ละ distro แยกต่างหาก แต่บางครั้งมีปัญหาในทางปฏิบัติที่ป้องกันไม่ให้ (ไม่กำลังคนอย่างน้อย)

ดังนั้นสำหรับผู้ที่ต้องการ "ตรวจจับอัตโนมัติ" นี่คือสิ่งที่ฉันได้พบในชุด distros จำกัด (ด้านล่างเพิ่มเติม):

  • คุณสามารถบอกคนธรรมดาได้จาก:

    [[ `/sbin/init --version` =~ upstart ]] && echo yes || echo no
  • คุณสามารถบอก systemd จาก:

    [[ `systemctl` =~ -\.mount ]] && echo yes || echo no
  • คุณสามารถบอก sys-v init ได้จาก:

    [[ -f /etc/init.d/cron && ! -h /etc/init.d/cron ]] && echo yes

นี่คือการทดลองของฉันกับบรรทัดคำสั่งต่อไปนี้:

if [[ `/sbin/init --version` =~ upstart ]]; then echo using upstart;
elif [[ `systemctl` =~ -\.mount ]]; then echo using systemd;
elif [[ -f /etc/init.d/cron && ! -h /etc/init.d/cron ]]; then echo using sysv-init;
else echo cannot tell; fi

ในอินสแตนซ์ ec2 (ฉันรวมรหัส AMI ของสหรัฐอเมริกาด้วย):

  • ArchLinux: using systemd (ตั้งแต่2012.10.06 )
  • CentOS6.4 ami-52009e3b: ใช้การพุ่งพรวด
  • CentOS7 ami-96a818fe: การใช้ systemd
  • Debian 6 ami-80e915e9: using sysv-init
  • Debian 7.5 ami-2c886c44: using sysv-init
  • Debian 7.6 GCE container-vm: using sysv-init
  • RHEL 6.5 ami-8d756fe4: ใช้การพุ่งพรวด
  • SLES 11 ami-e8084981: ใช้ sysv-init
  • Ubuntu 10.04 ami-6b350a02: การใช้พุ่งพรวด
  • Ubuntu 12.04 ami-b08b6cd8: การใช้พุ่งพรวด
  • Ubuntu 14.04 ami-a427efcc: การใช้พุ่งพรวด
  • Ubuntu 14.10 และอายุน้อยกว่า: ใช้ systemd
  • AWS linux 2014.3.2 ami-7c807d14: การใช้พุ่งพรวด
  • Fedora 19 ami-f525389c: กำลังใช้ systemd
  • Fedora 20 ami-21362b48: ใช้ systemd

เพื่อให้ชัดเจน: ฉันไม่ได้อ้างว่านี่เป็นสิ่งที่เข้าใจผิดได้! มันเกือบจะไม่แน่นอน โปรดทราบว่าเพื่อความสะดวกฉันใช้การแข่งขัน bash regexp ซึ่งไม่สามารถใช้ได้ทุกที่ ตอนนี้ดีพอสำหรับฉันแล้ว อย่างไรก็ตามหากคุณพบ distro ที่มันล้มเหลวโปรดแจ้งให้เราทราบและฉันจะพยายามแก้ไขหากมี EC2 AMI ที่สร้างปัญหาขึ้นมาใหม่ ...


5
ตามเอกสารของ systemd ( sd_booted (3) ) วิธีที่ถูกต้องในการตรวจสอบ systemd คือการตรวจสอบว่ามีไดเรกทอรี/run/systemd/systemอยู่หรือไม่
Robie Basak

1
ฉันจะเพิ่มการตรวจจับนี้launchdระบบ init บน macOS: [[ $(ps 1) =~ 'launchd' ]] && echo yes || echo noทดสอบบน MacBookPro, macOS Sierra เวอร์ชั่น 10.12
Tony

ฉันต้องการเพิ่ม busybox:if [ -h /sbin/init -a $(readlink /sbin/init | grep busybox | wc -l) -gt 0 ]; then echo yes; else echo no; fi
Astrinus

18

ใช้กระบวนการ

ดูผลลัพธ์จากpsคำสั่งสองสามคำที่สามารถตรวจจับเวอร์ชันต่างๆของsystemd& upstartซึ่งสามารถสร้างขึ้นมาได้เช่น:

พุ่งพรวด

$ ps -eaf|grep '[u]pstart'
root       492     1  0 Jan02 ?        00:00:00 upstart-udev-bridge --daemon
root      1027     1  0 Jan02 ?        00:00:00 upstart-socket-bridge --daemon

systemd

$ ps -eaf|grep '[s]ystemd'
root         1     0  0 07:27 ?        00:00:03 /usr/lib/systemd/systemd --switched-root --system --deserialize 20
root       343     1  0 07:28 ?        00:00:03 /usr/lib/systemd/systemd-journald
root       367     1  0 07:28 ?        00:00:00 /usr/lib/systemd/systemd-udevd
root       607     1  0 07:28 ?        00:00:00 /usr/lib/systemd/systemd-logind
dbus       615     1  0 07:28 ?        00:00:13 /bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation

การให้ความสนใจกับชื่อของกระบวนการที่ PID # 1 ยังสามารถทำให้เข้าใจได้ว่าระบบ init นั้นกำลังใช้งานอยู่ บน Fedora 19 (ซึ่งใช้systemdตัวอย่างเช่น:

UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 07:27 ?        00:00:03 /usr/lib/systemd/systemd --switched-root --system --deserialize 20

initแจ้งให้ทราบว่าไม่ บน Ubuntu /sbin/initกับพุ่งพรวดก็ยังคง

$ ps -efa|grep init
root         1     0  0 Jan02 ?        00:00:03 /sbin/init

หมายเหตุ:แต่ใช้สิ่งนี้ด้วยความระมัดระวัง มีอะไรที่ไม่ตั้งอยู่ในหินที่บอกว่าระบบ init โดยเฉพาะอย่างยิ่งมีการใช้งานบน distro ให้มีจะมีsystemdเป็น PID # 1

ทั่วไป

$ (ps -eo "ppid,args" 2>/dev/null || echo "ps call error") \
    | awk 'NR==1 || $1==1' | less
 PPID   COMMAND
    1   /lib/systemd/systemd-journald
    1   /lib/systemd/systemd-udevd
    1   /lib/systemd/systemd-timesyncd

ดูกระบวนการที่มี ppid 1 (ชายน์ของกระบวนการเริ่มต้น) (บางส่วน) ชื่อกระบวนการลูกอาจชี้ไปที่ระบบ init ที่ใช้งานอยู่

ระบบไฟล์

หากคุณซักถามinitปฏิบัติการคุณสามารถรับข้อมูลจากมันได้เช่นกัน เพียงแยกวิเคราะห์--versionผลลัพธ์ ตัวอย่างเช่น:

พุ่งพรวด

$ sudo /sbin/init --version
init (upstart 1.5)
Copyright (C) 2012 Scott James Remnant, Canonical Ltd.

This is free software; see the source for copying conditions.  There is NO warranty; not even for MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.

systemd

$ type init
init is /usr/sbin/init

หมายเหตุ:ความจริงที่initไม่ได้อยู่ในตำแหน่งมาตรฐานนั้นเป็นเพียงคำใบ้ / บอกเล็กน้อย มันตั้งอยู่เสมอใน/sbin/initระบบ sysvinit

sysvinit

$ type init
init is /sbin/init

นอกจากนี้:

$ sudo init --version
init: invalid option -- -
Usage: init 0123456SsQqAaBbCcUu

สรุปผลการวิจัย

ดังนั้นจึงไม่มีวิธีใดที่จะทำได้ แต่คุณสามารถกำหนดชุดการตรวจสอบที่จะระบุระบบเริ่มต้นที่คุณใช้ด้วยความมั่นใจในระดับสูง


วิธีการเกี่ยวกับ:pgrep systemd >/dev/null && echo init system: systemd
Marco

ขอบคุณนี่คือสิ่งที่ฉันกำลังมองหา: ขั้นตอนบางอย่างที่ต้องทำเพื่อลองกำหนดระบบเริ่มต้น
user369450

1
PID # 1 ไม่จำเป็นต้องใช้/usr/lib/systemd/systemdถ้า systemd ถูกใช้มันเป็นข้อสันนิษฐานที่ผิดพลาด ในระบบของฉันเช่น PID # 1 คือ/sbin/init(ฉันใช้ systemd) มันขึ้นอยู่กับการกระจาย
Marco

ในการติดตั้ง kubuntu 15.04 ของฉันฉันดูเหมือนว่าทั้งคู่มี systemd และ sysvinit ไม่ทราบว่าทำไมหรือหมายความว่าอย่างไรเพียงแค่พูด .. pgrep systemd >/dev/null && echo init system: systemd -> init system: systemdและtype init -> init is /sbin/init
dotnetCarpenter

12

ไม่ได้มีประสิทธิภาพ แต่ดูเหมือนว่าฉันจะทำงาน

strings /sbin/init | grep -q "/lib/systemd" && echo SYSTEMD
strings /sbin/init | grep -q "sysvinit" && echo SYSVINIT
strings /sbin/init | grep -q "upstart" && echo UPSTART

มันจะพิมพ์บรรทัดเพิ่มเติมหากมีมากกว่าหนึ่งสายตรงซึ่งสามารถแปลเป็น "ไม่สามารถเดาได้" สตริงที่ใช้ใน grep สามารถแก้ไขได้เล็กน้อย แต่เมื่อทดสอบในระบบปฏิบัติการต่อไปนี้ฉันจะได้หนึ่งบรรทัด

  • RHEL 6.4 [UPSTART]
  • RHEL ES 4 (ปรับปรุงล่าสุด 7) [SYSVINIT]
  • Ubuntu 16.04.1 LTS [SYSTEMD]
  • Ubuntu 14.04.2 LTS [UPSTART]
  • Fedora ปล่อย 23 (เชลล์ออนไลน์) [SYSTEMD]
  • Debian GNU / Linux 7 (เชลล์ออนไลน์) [SYSTEMD]

วิธีการที่ง่ายกว่าของโซลูชันเดียวกัน (แต่จะหยุดที่คู่แรก)

strings /sbin/init |
  awk 'match($0, /(upstart|systemd|sysvinit)/) { print toupper(substr($0, RSTART, RLENGTH));exit; }'

คำตอบแรกที่ดี ยินดีต้อนรับสู่ unix.se!
Olivier Dulac

ฉันเพิ่งลองทำสิ่งนี้กับอิมเมจเทียบท่าเริ่มต้นของ Gentoo ที่ติดตั้ง OpenRC แล้วและส่งคืน SYSVINIT ตามwiki.gentoo.org/wiki/Comparison_of_init_systemsค่าเริ่มต้นสำหรับ Gentoo คือ OpenRC แต่ปรากฏว่า OpenRC ใช้ sysvinit เมื่อฉันลองใช้คำสั่ง OpenRC ฉันจะได้รับ "คุณกำลังพยายามเรียกใช้บริการ OpenRC บนระบบที่ openrc ไม่สามารถบู๊ตได้" มีวิธีที่จะแยกแยะระหว่าง sysvinit ที่เหมาะสมและ OpenRC โดยใช้ sysvinit หรือไม่?
ทิวดอร์

9

บางครั้งมันง่ายเหมือนการใช้ls :

$ ls -l /sbin/init
lrwxrwxrwx 1 root root 20 juin  25 12:04 /sbin/init -> /lib/systemd/systemd

ฉันเดาว่าถ้า/sbin/initไม่ใช่ลิงก์สัญลักษณ์คุณจะต้องตรวจสอบคำแนะนำเพิ่มเติมต่อไปนี้ในคำตอบอื่น ๆ


3
  1. นี่คือสิ่งที่แพคเกจเฉพาะสำหรับ distro มีมากขึ้นในการติดตั้งซอฟต์แวร์อย่างถูกต้องมากกว่าเพียงแค่การตรวจสอบระบบ init Distros จำนวนมากใช้ SysVinit แต่ไม่ใช่ทุกคนที่เขียนสคริปต์ init ในลักษณะเดียวกัน วิธีที่เหมาะสมในการแก้ไขปัญหานี้คือการรวมชุดข้อมูลที่แตกต่างกันทั้งหมดแล้วรวมเข้าด้วยกันโดยใช้ไฟล์ข้อมูลจำเพาะที่มีชื่อ distro-specific dependency สำหรับ rpm distros, ไฟล์ deb สำหรับระบบที่ใช้ apt เป็นต้น distros เกือบทั้งหมดมีคุณสมบัติของแพ็คเกจ สามารถเขียนที่มีการอ้างอิงสคริปต์สคริปต์เริ่มต้นและอื่น ๆ อย่าคิดค้นวงล้อใหม่ที่นี่

  2. ไม่ซึ่งนำเรากลับมาที่ 1 หากคุณต้องการทุบตีมันควรจะเป็นการพึ่งพา คุณสามารถระบุการตรวจสอบนี้เป็นส่วนหนึ่งของสคริปต์กำหนดค่าของคุณ แต่ควรอยู่ในรายละเอียดแพ็คเกจ

แก้ไข:ธงใช้สคริปต์การกำหนดค่าของคุณเช่น หรือ--with upstart --without sysvinitเลือกค่าเริ่มต้นที่มีสติแล้วสคริปต์ที่จัดทำแพคเกจซอฟต์แวร์ของคุณสำหรับ distros อื่นสามารถเลือกที่จะเรียกใช้สิ่งนี้ด้วยตัวเลือกอื่น ๆ


อืมดังนั้นมันดูเหมือนว่าฉันไม่มีโซลูชัน 'หนึ่งสคริปต์ที่ควบคุมกฎทั้งหมด' ฉันเคยเห็นหลายโปรแกรมที่ใช้ autoconf หรือคล้ายกันเพื่อจัดการกับสิ่งต่าง ๆ ข้ามแพลตฟอร์ม แต่ดูเหมือนจะไม่เป็นเครื่องมือที่เหมาะสมสำหรับแอปพลิเคชันของฉัน การรักษาเวอร์ชันสำหรับแต่ละแพลตฟอร์มนั้นเป็นทางออกที่เชื่อถือได้หรือไม่
beatgammit

สคริปต์การติดตั้งหนึ่งตัวสำหรับกฎทั้งหมดคือ BadIdea มันล้มเหลวในสถานที่มากกว่าที่มันทำงาน Autoconf นั้นดีเท่าที่จะไป พยายามอย่างเต็มที่ในการรักษาจุดสิ้นสุดของซอฟต์แวร์ให้อยู่ในระดับสามัญที่สุดเท่าที่จะเป็นไปได้และรวมสคริปต์เริ่มต้นสำรองไว้ในแพ็คเกจของคุณ ข้อกำหนดคุณลักษณะการตั้งค่าแพคเกจสำหรับหลาย distros สำคัญ หากซอฟต์แวร์ของคุณดีคุณสามารถนำคนอื่นมาช่วยคุณจัดการบรรจุภัณฑ์ให้กับระบบอื่นได้
Caleb

@tjameson: ฉันเพิ่งรู้ว่าฉันลืมบิตที่สำคัญที่สุด สิ่งนี้มักจะทำโดยใช้สวิตช์ที่ส่งผ่านไปยังสคริปต์การกำหนดค่า รูทีนการสร้าง / แพ็กเกจของ distro แต่ละตัวสามารถเรียกสวิตช์ที่แตกต่างกันได้และการกำหนดค่า / สร้างของคุณจะต้องรู้ว่าสวิตช์ที่ผ่านนั้นไม่ได้ตรวจจับการกำหนดค่าซอฟต์แวร์ทั้งหมดที่เป็นไปได้
คาเลบ

@ Caleb- ใช่ฉันมีตรรกะนั้นอยู่ในนั้น แต่จับได้ดี ฉันหวังว่าจะมีวิธีในการดมกลิ่นระบบ init เพื่อใช้การคาดเดาที่ฉลาดกว่าค่าเริ่มต้นที่มีสติ
beatgammit

2

ใน Gentoo ให้ดูที่ pid 1:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0   4216   340 ?        Ss    2013   0:57 init [3]

ถ้าเป็นinitแล้วระบบ init OpenRCคือ ถ้าเป็นsystemdแล้วระบบ init systemdคือ

คุณสามารถตรวจสอบ Gentoo [ -f /etc/gentoo-release ]กับ

อีกวิธีหนึ่งใน Gentoo คือการใช้profile-config showซึ่งจะแสดงโปรไฟล์เริ่มต้นที่ใช้งานอยู่ โปรไฟล์ทั้งหมดยกเว้นทั้งสองสิ้นสุดใน / systemd ใช้ OpenRC init โปรดทราบว่าสิ่งเหล่านี้เป็นเพียงตัวแทนของค่าเริ่มต้นและเป็นไปได้ว่าผู้ใช้ได้ดำเนินการตามขั้นตอนเพื่อแทนที่ค่าเริ่มต้นนั้นและอาจไม่สามารถบ่งชี้ถึงผู้จัดการรางหญ้าที่ใช้งานจริง


เป็นใบ้คำถาม แต่ฉันจะตรวจสอบ pid 1 ได้อย่างไร
Faheem Mitha

ใช้pตัวเลือก (เหมือนกัน-pและ--pid) เพื่อเลือกโดย PID ps u --pid 1ข้อมูลข้างต้นเป็นจริงผลลัพธ์สำหรับ
José M. Benítez

2

On debian / sbin / init เป็น symlink ไปยัง init เริ่มต้นของคุณ

ls -l /sbin/init

จะให้ข้อมูลที่คุณต้องการ

$ ls -l /sbin/init 
lrwxrwxrwx 1 root root 20 nov 18 13:15 /sbin/init -> /lib/systemd/systemd

1
ไม่เช่นนั้น บน Ubuntu 14.04 ที่มี Upstart ไม่ใช่ symlink
muru

ติดตั้งระบบ init อื่นและตรวจสอบอีกครั้ง
rmorelli74

และที่อื่น ๆ ที่initฉันสามารถติดตั้งบน Ubuntu 14.04?
muru

... ทำไมไม่ sysv หรือ systemd
rmorelli74

1
ฉันไม่ต้องการ downvote ฉันแค่ต้องการให้คุณระบุรุ่นของ Debian ที่ใช้ได้ (และอาจจะใช้ถ้อยคำ "Debian-based" กับ "เด" เท่านั้นเพื่อที่ว่ามันจะกลายเป็นที่ถูกต้อง.)
Muru

2

เพียงแค่ greping เข้าสู่กระบวนการด้วย PID 1 จะบอกคุณ:

strings /proc/1/exe |grep -q sysvinit
strings /proc/1/exe |grep -q systemd

ไม่ได้ทุกสภาพแวดล้อมระบบปฏิบัติการดังกล่าวมีprocระบบแฟ้ม ...
Toby Speight

2

การตรวจสอบ descriptor ไฟล์สามารถช่วยได้เช่นกัน และมันก็มาจากการเรียกใช้ init (ปัจจุบันเดเบียนยืดอนุญาตให้มีการติดตั้งระบบ init เพิ่มเติม) :-)

$ ls -l /proc/1/fd |grep systemd
lrwx------ 1 root root 64 srp 14 13:56 25 -> /run/systemd/initctl/fifo
lr-x------ 1 root root 64 srp 14 13:56 6 -> /sys/fs/cgroup/systemd

$ ls -l /proc/1/fd |grep /run/initctl # sysvinit
lrwx------ 1 root root 64 srp 14 14:04 10 -> /run/initctl

$ ls -l /proc/1/fd |grep upstart
l-wx------ 1 root root 64 srp 13 16:09 13 -> /var/log/upstart/mysql.log.1 (delete
l-wx------ 1 root root 64 srp 13 16:09 9 -> /var/log/upstart/dbus.log.1 (deleted)

$ ls -l /proc/1/fd # busybox
total 0
lrwx------    1 root     root          64 Jan  1 00:00 0 -> /dev/console
lrwx------    1 root     root          64 Jan  1 00:00 1 -> /dev/console
lrwx------    1 root     root          64 Jan  1 00:00 2 -> /dev/console

อาจเป็นวิธีที่ปลอดภัยกว่าในการตรวจสอบcheck /proc/1/exebusybox โดยปกติแล้ว busybox จะใช้ symlink:

$ ls -l /proc/1/exe 
lrwxrwxrwx    1 root     root          0 Jan  1 00:00 /proc/1/exe -> /bin/busybox

ดังนั้นการตรวจสอบอาจเป็น:

{ ls -l /proc/1/fd |grep -q systemd && echo "init: systemd"; } || \
{ ls -l /proc/1/fd |grep -q /run/initctl && echo "init: sysvinit"; } || \
{ ls -l /proc/1/fd |grep -q upstart && echo "init: upstart"; } || \
{ ls -l /proc/1/exe |grep -q busybox && echo "init: busybox"; } || \
echo "unknown init"

นอกจากนี้ยังมีระบบที่มี systemd /run/systemd/systemมักจะมีไดเรกทอรี
pevik

2

ไม่ทราบเกี่ยวกับระบบอื่นแล้ว Debian (เสียงดัง) / หรือ Ubuntu (14.10.) แต่ฉันทดสอบปัญหาดังกล่าวด้วยfileคำสั่งเก่าแบบธรรมดา

file /sbin/init

ให้สิ่งนี้:

/sbin/init: symbolic link to 'upstart'

ระบบ Debian ที่มีsystemd(เช่น sid) แสดงสิ่งนี้:

# file /sbin/init 
/sbin/init: symbolic link to /lib/systemd/systemd

คุณทดสอบระบบอะไร ไม่มีสิ่งเช่น Debian / Ubuntu และสิ่งนี้ไม่ทำงานบน Debian คุณลองบน Ubuntu หรือไม่
terdon

ขออภัยในความสับสนนี้ฉันหมายถึง Debian (เสียงดัง) / หรือ Ubuntu (14.10) เอาท์พุทบนเดเบียน: file /sbin/init /sbin/init: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, BuildID[sha1]=0x8c68a736c6a4e6fadf22d5ac9debf11e79c6bdcd, stripped หมายความว่าเราใช้ SYSV ที่นี่ ผลลัพธ์สำหรับอูบุนตูแสดงในคำตอบของฉัน
zzeroo

ดังนั้นโซลูชันของคุณจึงดูเหมือนว่าจะใช้ได้เฉพาะเมื่อมีคนใช้งานพุ่งพรวดและ Ubuntu
terdon

@terdon: บนระบบ (RHEL, Fedora) ที่รัน systemd มันจะส่งกลับ "symbolic link to ... systemd"; บนระบบ (Ubuntu) กำลังเริ่มต้นทำงานมันจะส่งคืน "ลิงก์สัญลักษณ์ไปยังพุ่งพรวด"; บนระบบ (RHEL, Ubuntu, Debian) ที่รัน SysV init จะส่งคืน "executable" ในขณะที่การสำรวจแบบครอบคลุมแทบจะไม่และวิธีการนี้ไม่สามารถเข้าใจผิดได้ 100% แต่ก็ใกล้เคียงกับ "ทำงานอย่างน้อย distros สำคัญ" มากกว่า "เพียงแค่ upstart และ Ubuntu"!
psmears

1
@psmears หากยังใช้งานได้กับบางระบบ systemd นั่นจะดีกว่า (แต่ไม่ได้กล่าวถึงในคำตอบนี้) ฉันเพิ่งทดสอบกับ Debian ที่กำลังเรียกใช้ sysvinit และสาม Ubuntus (10.04,12.04 และ 14.04 ทั้งหมดที่เริ่มต้นทำงาน) และ file /sbin/initกลับ "ปฏิบัติการ" ในทุกระบบ มันกลับมาเหมือนกันใน CentOS 5.8, SLES 10, Ubuntu 8.04, โดยพื้นฐานแล้วทุกระบบเดียวที่ฉันสามารถทำได้ ดังนั้นเท่าที่ฉันสามารถบอกได้ว่ามันไม่ได้ผลแม้แต่การพุ่งพรวดและ Ubuntu
terdon

2

ฉันมีปัญหาเดียวกันนี้และทำการทดสอบจำนวนมากในเครื่อง RedHat / CentOS / Debian / Ubuntu / Mint นี่คือสิ่งที่ฉันลงเอยด้วยผลลัพธ์ที่ดี

  1. ค้นหาชื่อของไฟล์เรียกทำงานด้วย PID 1:

    ps -p 1

    ถ้ามันเป็น systemd หรือพุ่งพรวดปัญหาได้รับการแก้ไข หากเป็น "init" อาจเป็น symlink หรือชื่ออื่นที่ไม่ใช่ชื่อตรงไปตรงมา ไปข้างหน้า

  2. ค้นหาพา ธ จริงของไฟล์ที่เรียกใช้งานได้ (ทำงานเป็นรูทเท่านั้น):

    ls -l `which init`

    หากinitเป็น symlink ไปสู่การเริ่มต้นระบบหรือ systemd แก้ไขปัญหา มิฉะนั้นเป็นเรื่องเกือบแน่ใจว่าคุณมี SysV init แต่มันอาจเป็นปฏิบัติการที่ผิด ไปข้างหน้า

  3. ค้นหาแพ็คเกจที่จัดทำไฟล์ปฏิบัติการได้ น่าเสียดายที่นี่ขึ้นอยู่กับ distro:

    dpkg-query -S (executable real path) # Debian  
    rpm -qf (executable real path) # RedHat  

จากนั้นหากคุณต้องการสคริปต์ที่ (ส่วนที่สนุกที่สุด IMHO) เหล่านี้คือหนึ่งใน liners ของฉัน (ทำงานเป็นราก):

ls -l $(which $(ps -p 1 o comm)) | awk '{ system("dpkg-query -S "$NF) }' # Debian  

ls -l $(which $(ps -p 1 o comm)) | awk '{ system("rpm -qf "$NF) }' # RedHat  

1
ไม่ใช่ทุกระบบปฏิบัติการที่ระบุมี dpkg หรือ rpm (ปัญหานี้ไม่เฉพาะเจาะจงกับคำตอบของคุณ BTW)
Toby Speight

@ toby-speight ใช่แน่นอน หมายเหตุฉันระบุไว้ในคำตอบของฉันเพียงเพื่อให้ข้อ จำกัด ชัดเจน
Emerson Prado

สำหรับขั้นตอนที่ 3 คุณสามารถเรียกใช้init --versionเพื่อรับข้อมูลได้
jarno

1

นี่เป็นเรื่องง่ายสำหรับระบบเริ่มต้นบางระบบ สำหรับ systemd:

test -d /run/systemd/system

สำหรับคนธรรมดา:

initctl --version | grep -q upstart

สำหรับสิ่งอื่นคุณสามารถสันนิษฐานได้จาก distro (launchd บน OS X, sysvinit บน Debian, OpenRC บน Gentoo)


"สมมติจาก distro" ไม่ทำงานสำหรับ Debian ที่สนับสนุน inits อย่างน้อยสามที่แตกต่างกัน ...
Toby Speight

1

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

detect_distro()
{
  # init process is pid 1
  INIT=`ls -l /proc/1/exe`
  if [[ $INIT == *"upstart"* ]]; then
    SYSTEMINITDAEMON=upstart
  elif [[ $INIT == *"systemd"* ]]; then
    SYSTEMINITDAEMON=systemd
  elif [[ $INIT == *"/sbin/init"* ]]; then
    INIT=`/sbin/init --version`
    if [[ $INIT == *"upstart"* ]]; then
      SYSTEMINITDAEMON=upstart
    elif [[ $INIT == *"systemd"* ]]; then
      SYSTEMINITDAEMON=systemd
    fi
  fi

  if [ -z "$SYSTEMINITDAEMON" ]; then
    echo "WARNING: Unknown distribution, assuming defaults - this may fail." >&2
  else
    echo "Init system discovered: $SYSTEMINITDAEMON"
  fi
}

1
ฉันคิดว่าการใช้/procความสัมพันธ์นี้กับ Linux (ถ้ากำหนดค่าอย่างเหมาะสม) และหนึ่งหรือสองอื่น ๆ - มันไกลจากสากลอย่างแน่นอน
Toby Speight

1

มีข้อผิดพลาดความเข้ากันได้มากมายเมื่อทดสอบ systemd vs initd ใช้งานได้จริงบน OpenSuSE 42.1:ps --pid 1 | grep -q systemd && echo 'systemd' || echo 'init'


1

สำหรับsystemd:

if [[ `systemctl is-system-running` =~ running ]]; then echo using systemd; fi

downvoting เนื่องจากคำตอบนี้ไม่ได้ให้ข้อมูลใหม่หรือข้อมูลที่แตกต่างเมื่อเปรียบเทียบกับคำตอบที่มีอยู่มากมาย
jayhendren

@ jayhendren ฉันไม่เห็นตัวอย่างข้อมูลนี้ที่อื่น มันไม่ได้สมบูรณ์ในตัวเองและอาจจะดีกว่ายืนเป็นความคิดเห็นกับคำตอบunix.stackexchange.com/a/164092/100397โดย TVE
roaima

โอ้คุณพูดถูก @roaima มันไม่เหมือนกับคนอื่น ๆ ฉันค้นหาหน้าสำหรับสตริงไม่มากเกินไปโดยเฉพาะ :)
jayhendren

1
นี้น่าจะเป็นไกลโดยคำตอบที่ถูกต้องที่สุด :)
แจ็คโอคอนเนอร์

1

วิธีการแก้ปัญหาของฉัน: ตรวจสอบคำสั่งที่ทำงานเป็นกระบวนการที่มี ID 1

case `cat /proc/1/comm` in
    init)    echo Init ;;
    systemd) echo SystemD ;;
    # add here other patterns
    *)       echo "unknown: '`cat /proc/1/comm`'" ;;
esac

ในขณะนี้ฉันเข้าถึงเฉพาะเครื่อง Init และ SystemD เท่านั้นดังนั้นฉันไม่สามารถบอกได้ว่าจะตรวจพบการพุ่งพรวดหรือ macOS (OS X) ได้อย่างไร แต่ฉันจะค้นหาต่อไป


0
check(){
    if hash systemctl 2>/dev/null;
    then
        echo "there is systemd"
    fi

    if hash initctl 2>/dev/null;
    then
        echo "there is upStart"
    fi

    if [ -f "/etc/inittab"];
    then
        echo "there is systemV"
    fi
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.