Phát hiện hệ thống init bằng shell


90

Điều này có thể liên quan nhiều hơn đến việc phát hiện các hệ điều hành, nhưng tôi đặc biệt cần hệ thống init hiện đang sử dụng trên hệ thống.

Fedora 15 và Ubuntu hiện sử dụng systemd, Ubuntu đã từng sử dụng Upstart (mặc định thời gian dài cho đến 15.04), trong khi những người khác sử dụng các biến thể của System V.

Tôi có một ứng dụng mà tôi đang viết để trở thành một daemon đa nền tảng. Các tập lệnh init đang được tạo động dựa trên các tham số có thể được truyền vào cấu hình.

Những gì tôi muốn làm là chỉ tạo tập lệnh cho hệ thống init cụ thể mà họ đang sử dụng. Bằng cách này, tập lệnh cài đặt có thể được chạy một cách hợp lý mà không cần tham số là root và trình nền có thể được "cài đặt" tự động.

Đây là những gì tôi nghĩ ra:

  • Tìm kiếm systemd, upstart, v.v. trong / bin
  • So sánh / Proc / 1 / comm với systemd, upstart, v.v.
  • Hỏi người dùng

Điều gì sẽ là cách chéo / nền tảng tốt nhất để làm điều này?

Loại liên quan, Tôi có thể phụ thuộc vào bash để chiếm đa số * nix hay là phụ thuộc vào phân phối / HĐH?

Nền tảng mục tiêu:

  • hệ điều hành Mac
  • Linux (tất cả các bản phân phối)
  • BSD (tất cả các phiên bản)
  • Solaris, Minix và * nix khác

1
Chỉ cần thêm hai xu của tôi, bash không được cài đặt theo mặc định trên FreeBSD.
Chinmay Kanchi

@tjameson, bạn đã tìm được cách trực tiếp hơn chưa? Tôi đang tìm kiếm điều tương tự nhưng câu trả lời ở đây chỉ là hướng dẫn chứ không phải câu trả lời trực tiếp. Cụ thể là 1) vị trí tập lệnh để tìm kiếm và 2) phát hiện hệ thống init có hiệu lực, trong trường hợp có nhiều vị trí được cài đặt (bash đã được trả lời trực tiếp).
n611x007

3
@naxa - Câu trả lời ngắn, không. Câu trả lời dài, bạn có thể nhận được khá xa với ps -p 1 -o command(in đường dẫn đến hiện tại init). Trên Arch Linux và Fedora (IIRC), đó là một liên kết tượng trưng đến systemdnhị phân (có thể giống nhau trên tất cả các systemdhệ thống). Trên upstart, init --helpsẽ in thông tin sử dụng, và trên hộp của tôi, upstartđược đề cập đến nơi nó nói ai sẽ gửi email. Trên FreeBSD (sysV), điều này sẽ trả về lỗi. Có thể có manh mối tương tự trên các hệ thống khác, nhưng kể từ khi đặt câu hỏi này, tôi đã quyết định chỉ tạo chúng cho tất cả các nền tảng và tạo các gói riêng biệt cho mỗi hệ thống.
beatgammit

cảm ơn thông tin tuyệt vời Nhảy từ đó tôi đã học được rằng sudo lsof -a -p 1 -d txtcó thể cho kết quả chính xác hơn nữa. pscó thể in một tên tùy ý, trong khi với lsofbạn sẽ có được đường dẫn thực thi thực sự. (Xem câu hỏi của tôi unix.stackexchange.com/questions/102453/... )
n611x007

1
Không có câu trả lời hoặc nhận xét nào trong câu hỏi được liên kết là bash liên quan. Các giải pháp nên được áp dụng cho trường hợp của bạn là tốt.
Marco

Câu trả lời:


30

Đối với câu hỏi thứ hai, câu trả lời là không và bạn nên xem Tài nguyên để lập trình shell di động .

Về phần đầu tiên - trước hết, bạn chắc chắn phải cẩn thận. Tôi muốn nói thực hiện một số thử nghiệm để đảm bảo - bởi vì thực tế là ai đó đã cài đặt systemd (ví dụ), không có nghĩa là nó thực sự được sử dụng làm mặc định init. Ngoài ra, nhìn vào /proc/1/commcó thể gây hiểu nhầm, bởi vì một số cài đặt của các chương trình init khác nhau có thể tự động tạo /sbin/initmột liên kết cứng symlink hoặc thậm chí là một phiên bản được đổi tên của chương trình chính của chúng.

Có lẽ điều hữu ích nhất có thể là xem xét loại init script - bởi vì đó là những gì bạn thực sự sẽ tạo ra, bất kể điều gì chạy chúng.

Là một lưu ý phụ, bạn cũng có thể có một cái nhìn về OpenRC nhằm mục đích cung cấp một cấu trúc các tập lệnh init tương thích với cả hệ thống Linux và BSD.


2
Bạn có ý nghĩa gì khi "nhìn vào kiểu init script"? Thông thường các hệ thống init khác nhau đặt tập lệnh / tập tin của chúng ở đâu đó bên cạnh /etc/init, như systemd đặt chúng vào /etc/systemd. Nếu tôi có kịch bản của mình tìm kiếm những thứ này, nó có thể mất một chút thời gian. Oh, và cảm ơn vì liên kết BTW cho lập trình shell di động.
beatgammit

1
Tôi muốn nói rằng một số triển khai init có thể được điều chỉnh để sử dụng các loại và vị trí của các tập lệnh init khác nhau (như /etc/rc.d/hoặc /etc/init.d/). Và bạn nên điều chỉnh đúng chương trình của mình khi cài đặt để sử dụng cấu trúc được sử dụng trên hệ thống nhất định.
rozcietrzewiacz

2
Vì vậy, bạn đang nói rằng không có cách đáng tin cậy để phát hiện hệ thống init theo chương trình? Có người dùng vượt qua các tham số chắc chắn an toàn hơn, nhưng nếu người dùng không truyền bất cứ thứ gì vào, cách tốt nhất để đoán là gì?
beatgammit

Tôi không biết điều gì sẽ là cách tốt nhất cho chương trình của bạn - tất cả phụ thuộc vào hệ thống nào chương trình sẽ chạy. Tôi đã không sử dụng quá nhiều bản phân phối, nhưng tôi đã cố gắng chia sẻ những quan sát của mình để giúp bạn. Đó là một đoạn kịch bản khó khăn mà bạn sắp thử và tôi đã cố gắng cung cấp cho bạn một số quan điểm về lĩnh vực này - bạn phải tự mình đi đến câu trả lời cuối cùng hoặc chờ thêm gợi ý.
rozcietrzewiacz

Thật tuyệt, cảm ơn vì tất cả sự giúp đỡ của bạn. Bạn chắc chắn đã chỉ cho tôi đi đúng hướng.
beatgammit

58

Tôi đã tự mình bước vào vấn đề này và quyết định làm một số thử nghiệm. Tôi hoàn toàn đồng ý với câu trả lời rằng một người nên đóng gói riêng cho từng bản phân phối, nhưng đôi khi có những vấn đề thực tế ngăn cản điều đó (không phải ít nhất là nhân lực).

Vì vậy, đối với những người muốn "tự động phát hiện" đây là những gì tôi đã tìm thấy trên một bộ phân phối giới hạn (nhiều hơn bên dưới):

  • Bạn có thể nói mới bắt đầu từ:

    [[ `/sbin/init --version` =~ upstart ]] && echo yes || echo no
  • Bạn có thể nói với systemd từ:

    [[ `systemctl` =~ -\.mount ]] && echo yes || echo no
  • Bạn có thể nói với sys-v init từ:

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

Dưới đây là các thử nghiệm của tôi với dòng lệnh sau:

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

trên các trường hợp ec2 (Tôi bao gồm id AMI phía đông):

  • ArchLinux: sử dụng systemd (từ 2012.10.06 )
  • CentOS6.4 ami-52009e3b: sử dụng mới bắt đầu
  • CentOS7 ami-96a818fe: sử dụng systemd
  • Debian 6 ami-80e915e9: sử dụng sysv-init
  • Debian 7.5 ami-2c886c44: sử dụng sysv-init
  • Debian 7.6 GCE container-vm: sử dụng sysv-init
  • RHEL 6.5 ami-8d756fe4: sử dụng mới bắt đầu
  • SLES 11 ami-e8084981: sử dụng sysv-init
  • Ubuntu 10.04 ami-6b350a02: sử dụng mới bắt đầu
  • Ubuntu 12.04 ami-b08b6cd8: sử dụng mới bắt đầu
  • Ubuntu 14.04 ami-a427efcc: sử dụng mới bắt đầu
  • Ubuntu 14.10 trở xuống: sử dụng systemd
  • AWS linux 2014.3.2 ami-7c807d14: sử dụng mới nhất
  • Fedora 19 ami-f525389c: sử dụng systemd
  • Fedora 20 ami-21362b48: sử dụng systemd

Chỉ cần rõ ràng: Tôi không tuyên bố rằng điều này là hoàn hảo! , nó gần như chắc chắn là không. Cũng lưu ý rằng để thuận tiện, tôi sử dụng các kết hợp regash bash, không có sẵn ở mọi nơi. Trên đây là đủ tốt cho tôi ngay bây giờ. Tuy nhiên, nếu bạn tìm thấy một bản phân phối bị lỗi, vui lòng cho tôi biết và tôi sẽ cố gắng khắc phục nếu có EC2 AMI tái tạo sự cố ...


5
Theo tài liệu systemd ( sd_boote (3) ), cách chính xác để kiểm tra systemd là kiểm tra xem thư mục /run/systemd/systemcó tồn tại không.
Robie Basak

1
Tôi sẽ thêm vào phát hiện này launchd, hệ thống init trên macOS: [[ $(ps 1) =~ 'launchd' ]] && echo yes || echo nođã thử nghiệm trên MacBookPro, macOS Sierra Phiên bản 10.12
Tony

Tôi cũng sẽ thêm busybox:if [ -h /sbin/init -a $(readlink /sbin/init | grep busybox | wc -l) -gt 0 ]; then echo yes; else echo no; fi
Astrinus

18

Sử dụng các quy trình

Nhìn vào đầu ra từ một vài pslệnh có thể phát hiện các phiên bản khác nhau của systemd& upstart, có thể được tạo như vậy:

mới bắt đầu

$ 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

hệ thống

$ 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

Chú ý đến tên của quy trình mà PID # 1 cũng có khả năng làm sáng tỏ hệ thống init nào đang được sử dụng. Trên Fedora 19 (sử dụng systemd, ví dụ:

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

Chú ý là không init. Trên Ubuntu với Upstart, nó vẫn còn /sbin/init.

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

LƯU Ý: Nhưng sử dụng điều này với một chút thận trọng. Không có bất cứ điều gì đặt trong đá nói rằng một hệ thống init đặc biệt được sử dụng trên một distro cho đãsystemdnhư PID # 1.

chung

$ (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

Nhìn vào các quy trình với ppid 1 (con của quá trình init). (Một số) tên quy trình con có thể trỏ đến hệ thống init đang sử dụng.

Hệ thống tập tin

Nếu bạn thẩm vấn initthực thi, bạn cũng có thể nhận được một số thông tin từ nó. Đơn giản chỉ cần phân tích cú pháp --versionđầu ra. Ví dụ:

mới bắt đầu

$ 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.

hệ thống

$ type init
init is /usr/sbin/init

LƯU Ý: Thực tế initlà không ở vị trí tiêu chuẩn của nó là một chút gợi ý / nói. Nó luôn nằm trong /sbin/initcác hệ thống sysvinit.

hệ thống

$ type init
init is /sbin/init

Ngoài ra này:

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

Kết luận

Vì vậy, dường như không có một cách nào để làm điều đó, nhưng bạn có thể tạo ra một bộ kiểm tra để xác định chính xác hệ thống init nào bạn đang sử dụng với độ tin cậy khá cao.


Làm thế nào về:pgrep systemd >/dev/null && echo init system: systemd
Marco

Cảm ơn bạn, đây chính xác là những gì tôi đang tìm kiếm: một số bước cần thực hiện để cố gắng xác định hệ thống init.
dùng369450

1
PID # 1 không nhất thiết phải là /usr/lib/systemd/systemdnếu systemd được sử dụng, đó là một giả định sai. Trên hệ thống của tôi, ví dụ, PID # 1 là /sbin/init(tôi sử dụng systemd). Đó là phụ thuộc phân phối.
Marco

Trên bản cài đặt kubfox 15.04 của tôi, tôi có cả systemd và sysvinit. Không biết tại sao hoặc điều đó có nghĩa là gì, chỉ cần nói .. pgrep systemd >/dev/null && echo init system: systemd -> init system: systemdtype init -> init is /sbin/init
dotnetCarpenter

12

Không hiệu quả nhưng tôi dường như làm việc.

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

Nó sẽ in nhiều dòng hơn nếu nhiều hơn một chuỗi trùng khớp, có thể được dịch thành "Không thể đoán". Các chuỗi được sử dụng trong grep có thể được sửa đổi một chút nhưng khi được kiểm tra trong hệ điều hành sau tôi luôn có một dòng.

  • RHEL 6.4 [UPSTART]
  • RHEL ES 4 (Cập nhật Nahant 7) [SYSVINIT]
  • Ubuntu 16.04.1 LTS [HỆ THỐNG]
  • Ubuntu 14.04.2 LTS [UPSTART]
  • Fedora phát hành 23 (vỏ trực tuyến) [HỆ THỐNG]
  • Debian GNU / Linux 7 (vỏ trực tuyến) [HỆ THỐNG]

Một cách tiếp cận đơn giản hơn của cùng một giải pháp (nhưng nó dừng lại ở trận đấu đầu tiên)

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

câu trả lời đầu tiên tốt đẹp. Chào mừng đến với unix.se!
Olivier Dulac

Tôi vừa thử điều này trên một hình ảnh docker mặc định Gentoo đã cài đặt OpenRC và nó đã trả về SYSVINIT. Theo wiki.gentoo.org/wiki/Comparison_of_init_systems mặc định cho Gentoo là OpenRC, nhưng có vẻ như OpenRC sử dụng sysvinit. Sau đó, khi tôi thử các lệnh OpenRC, tôi nhận được "Bạn đang cố chạy một dịch vụ OpenRC trên một hệ thống mà openrc không khởi động được." Có cách nào để phân biệt giữa sysvinit thích hợp và OpenRC bằng sysvinit không?
tudor

9

Đôi khi nó dễ như sử dụng ls :

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

Tôi đoán nếu /sbin/initkhông phải là một liên kết tượng trưng, ​​bạn sẽ phải kiểm tra thêm các đề xuất sau trong các câu trả lời khác.


3
  1. Đây là những gì các gói cụ thể dành cho. Có nhiều thứ để cài đặt phần mềm đúng cách hơn là chỉ phát hiện hệ thống init. Nhiều distro sử dụng SysVinit nhưng không phải tất cả chúng đều viết script init của chúng theo cùng một cách. Cách thích hợp để giải quyết vấn đề này là bao gồm tất cả các biến thể khác nhau và sau đó kết hợp nó bằng cách sử dụng các tệp spec với các tên phụ thuộc dành riêng cho phân phối vòng / phút, các tệp deb cho các hệ thống dựa trên apt, v.v. có thể viết bao gồm các phụ thuộc, tập lệnh, tập lệnh init, v.v. Đừng tái tạo bánh xe ở đây.

  2. Không. Điều này đưa chúng tôi trở lại 1. Nếu bạn cần bash thì đó phải là một sự phụ thuộc. Bạn có thể chỉ định kiểm tra này như một phần của tập lệnh cấu hình của mình, nhưng nó cũng phải có trong phần mô tả gói.

Chỉnh sửa: Sử dụng cờ trên tập lệnh cấu hình của bạn như --with upstarthoặc --without sysvinit. Chọn một mặc định lành mạnh, sau đó các tập lệnh đóng gói phần mềm của bạn cho các bản phát hành khác có thể chọn để chạy phần mềm này với các tùy chọn khác.


Hừm, vậy có vẻ như tôi không thể có một "kịch bản để thống trị tất cả". Tôi đã thấy rất nhiều chương trình sử dụng autoconf hoặc tương tự để xử lý các công cụ đa nền tảng, nhưng có vẻ như đó không phải là công cụ phù hợp cho ứng dụng của tôi. Là duy trì các phiên bản cho mỗi nền tảng thực sự là giải pháp đáng tin cậy duy nhất?
beatgammit

Một tập lệnh cài đặt để cai trị tất cả chúng là BadIdea. Nó kết thúc thất bại nhiều nơi hơn nó hoạt động. Autoconf là tốt như nó đi. Làm việc chăm chỉ để giữ phần cuối của phần mềm càng chung chung càng tốt và bao gồm các tập lệnh init thay thế trong gói của bạn. Thiết lập thông số kỹ thuật gói cho một số distro chính. Nếu phần mềm của bạn tốt, bạn có thể nhờ người khác giúp bạn với việc đóng gói phần mềm cho các hệ thống khác.
Caleb

@tjameson: Tôi mới nhận ra mình đã quên một chút quan trọng nhất. Loại điều này thường được thực hiện với các công tắc được chuyển đến tập lệnh cấu hình. Mỗi thói quen xây dựng / gói của distro có thể gọi các công tắc khác nhau và cấu hình / thực hiện của bạn chỉ phải biết công tắc nào được chuyển, không phát hiện tất cả các cấu hình phần mềm có thể.
Caleb

@ Caleb- Vâng, tôi đã có logic đó, nhưng nắm bắt tốt. Tôi đã hy vọng một cách để đánh hơi hệ thống init để sử dụng một dự đoán thông minh hơn là một mặc định lành mạnh.
beatgammit

2

Trên Gentoo, hãy xem 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]

Nếu có init, thì hệ thống init là OpenRC. Nếu có systemd, thì hệ thống init là systemd.

Bạn có thể phát hiện Gentoo với [ -f /etc/gentoo-release ].

Một phương pháp khác trên Gentoo là sử dụng profile-config show, nó sẽ hiển thị cấu hình mặc định nào đang được sử dụng. Tất cả các cấu hình ngoại trừ hai kết thúc trong / systemd đều sử dụng init OpenRC. Hãy nhớ rằng, đây chỉ là đại diện của một mặc định và có thể người dùng đã thực hiện các bước để ghi đè mặc định đó và có thể không phải là dấu hiệu của trình quản lý init thực sự đang sử dụng.


Câu hỏi ngớ ngẩn, nhưng làm thế nào để tôi kiểm tra pid 1?
Faheem Mitha

Sử dụng ptùy chọn (giống hệt -p--pid) để chọn bởi PID. Đoạn mã trên thực sự là đầu ra cho ps u --pid 1.
Jose M. Benítez

2

Trên debian / sbin / init là một liên kết tượng trưng đến init mặc định của bạn, vì vậy

ls -l /sbin/init

sẽ cung cấp cho bạn thông tin bạn đang tìm kiếm.

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

1
Không phải vậy. Trên Ubuntu 14.04 với Upstart, nó không phải là một liên kết tượng trưng.
muru

Cài đặt hệ thống init khác và kiểm tra lại.
rmorelli74

inittôi có thể cài đặt cái nào khác trên Ubuntu 14.04?
muru

... tại sao không sysv hoặc systemd?
rmorelli74

1
Tôi không muốn downvote, tôi chỉ muốn bạn chỉ định phiên bản Debian nào được áp dụng. (Và có lẽ chỉ viết lại cụm từ "dựa trên Debian" thành "Debian" để nó trở nên chính xác.)
muru

2

Chỉ cần tham gia vào quá trình với PID 1 sẽ cho bạn biết:

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

Không phải tất cả các OSe được đề cập đều có prochệ thống tập tin ...
Toby Speight

2

Ngoài ra kiểm tra mô tả tập tin có thể giúp đỡ. Và đó là từ thực tế đang chạy init (hiện tại Debian cho phép cài đặt nhiều hệ thống init hơn) :-)

$ 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

Có lẽ cách an toàn hơn để kiểm tra busybox sẽ là check /proc/1/exe, vì busybox thường sử dụng các liên kết tượng trưng:

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

Vì vậy, kiểm tra có thể là:

{ 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"

Ngoài ra các hệ thống với systemd thường có thư mục /run/systemd/system.
pevik

2

Không biết về các hệ thống khác sau đó là Debian (wheezy) / hoặc Ubuntu (14.10.) Nhưng tôi kiểm tra các vấn đề như vậy với filelệnh cũ đơn giản .

file /sbin/init

cho này:

/sbin/init: symbolic link to 'upstart'

Các hệ thống Debian có systemd(ví dụ sid) hiển thị điều này:

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

Bạn đã kiểm tra nó trên hệ thống nào? Không có thứ gì như Debian / Ubuntu và cái này không hoạt động trên Debian. Bạn đã thử nó trên Ubuntu chưa?
terdon

Xin lỗi vì sự nhầm lẫn này, ý tôi là Debian (khò khè) / hoặc Ubuntu (14.10.). Đầu ra trên debian: 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 có nghĩa là chúng tôi sử dụng SYSV ở đây. Đầu ra cho Ubuntu được hiển thị trong câu trả lời của tôi.
zzeroo

Chính xác, vì vậy giải pháp của bạn dường như chỉ hoạt động nếu một người tình cờ sử dụng upstart và Ubuntu.
terdon

@terdon: Trên các hệ thống (RHEL, Fedora) đang chạy systemd, nó trả về "liên kết tượng trưng đến ... systemd"; trên các hệ thống (Ubuntu) đang chạy, nó trả về "liên kết tượng trưng để khởi động"; trên các hệ thống (RHEL, Ubuntu, Debian) đang chạy SysV init, nó trả về "thực thi". Mặc dù đó hầu như không phải là một cuộc khảo sát toàn diện và phương pháp này rõ ràng không thể đánh lừa được 100%, nhưng rõ ràng nó gần với "hoạt động ít nhất là các bản phát hành chính" thay vì "chỉ mới bắt đầu và Ubuntu"!
psmears

1
@psmears nếu nó cũng hoạt động cho một số hệ thống systemd, điều đó thực sự tốt hơn (nhưng không được đề cập trong câu trả lời này). Tôi vừa thử nghiệm trên Debian chạy sysvinit và ba Ubuntus (10.04,12.04 và 14.04, tất cả đều chạy mới) và file /sbin/inittrả về "thực thi" trên tất cả các hệ thống. Nó cũng trả về tương tự trên CentOS 5.8, SLES 10, Ubuntu 8.04, về cơ bản mọi hệ thống tôi có thể sử dụng. Vì vậy, theo như tôi có thể nói, nó thậm chí không hoạt động đối với Ubuntu mới bắt đầu.
terdon

2

Tôi cũng gặp vấn đề tương tự và đã thực hiện rất nhiều thử nghiệm trong một số máy RedHat / CentOS / Debian / Ubuntu / Mint. Đây là những gì tôi đã kết thúc, với kết quả tốt.

  1. Tìm tên của tệp thực thi với PID 1:

    ps -p 1

    Nếu đó là systemd hoặc Upstart, vấn đề đã được giải quyết. Nếu là "init", nó có thể là một liên kết tượng trưng hoặc một cái gì đó khác với tên trả trước. Đi về phía trước.

  2. Tìm đường dẫn thực sự cho tệp thực thi (chỉ hoạt động như root):

    ls -l `which init`

    Nếu initlà một symlink đến Upstart hoặc systemd, vấn đề đã được giải quyết. Mặt khác, gần như chắc chắn rằng bạn có SysV init. Nhưng nó có thể là một thực thi sai tên. Đi về phía trước.

  3. Tìm gói cung cấp thực thi. Thật không may, điều này phụ thuộc vào distro:

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

Sau đó, nếu bạn muốn viết kịch bản đó (phần hài hước nhất, IMHO), đây là những đoạn một của tôi (chạy dưới dạng root):

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
Không phải tất cả các hệ điều hành được chỉ định đều có dpkg hoặc vòng / phút (vấn đề này không chỉ dành riêng cho câu trả lời của bạn, BTW).
Toby Speight

@ toby-speight Vâng, chắc chắn rồi. Lưu ý tôi đã nêu như vậy trong câu trả lời của tôi, chỉ để làm cho giới hạn rõ ràng.
Emerson Prado

Đối với bước 3, bạn có thể chạy init --versionđể lấy thông tin.
jarno

1

Điều này thực sự dễ dàng cho một số hệ thống init. Đối với hệ thống:

test -d /run/systemd/system

để bắt đầu:

initctl --version | grep -q upstart

đối với bất cứ điều gì khác, bạn chỉ có thể giả sử dựa trên bản phân phối (launchd trên OS X, sysvinit trên Debian, OpenRC trên Gentoo).


"Giả sử dựa trên bản phân phối" không hoạt động đối với Debian, trong đó ít nhất ba phần tử khác nhau được hỗ trợ ...
Toby Speight

1

Đây là một tập lệnh bash để thực hiện phát hiện. Nó chỉ kiểm tra khởi động và systemd tại thời điểm này, nhưng nên dễ dàng mở rộng. Tôi đã lấy này từ mã Tôi đã đóng góp cho tập lệnh cài đặt trình điều khiển 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
Tôi nghĩ rằng việc sử dụng các /procmối quan hệ này với Linux (nếu được cấu hình phù hợp) và một hoặc hai người khác - nó chắc chắn là không phổ biến.
Toby Speight

1

Có rất nhiều cạm bẫy tương thích khi thử nghiệm systemd vs initd. Điều này thực sự hoạt động trên OpenSuSE 42.1:ps --pid 1 | grep -q systemd && echo 'systemd' || echo 'init'


1

Dành cho systemd:

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

bỏ qua vì câu trả lời này không cung cấp bất kỳ thông tin mới hoặc khác so với nhiều câu trả lời hiện có.
jayhendren

@jayhendren Tôi không thấy đoạn trích này ở nơi khác. Bản thân nó chưa hoàn thiện và có lẽ sẽ tốt hơn khi bình luận về câu trả lời unix.stackexchange.com/a/164092/100394 của TvE
roaima

Oh bạn nói đúng @roaima. Nó không hoàn toàn giống như những người khác. Tôi đã tìm kiếm trang cho một chuỗi không quá cụ thể :)
jayhendren

1
Đây dường như là câu trả lời đúng nhất :)
Jack O'Connor

1

Giải pháp của tôi: kiểm tra lệnh đang chạy như tiến trình với 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

Hiện tại tôi chỉ có quyền truy cập vào các máy init và SystemD, vì vậy tôi không thể biết Upstart hoặc macOS (OS X) sẽ được phát hiện như thế nào, nhưng tôi sẽ tiếp tục tìm kiếm.


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
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.