Wykryj system init za pomocą powłoki


90

Może to mieć więcej wspólnego z wykrywaniem systemów operacyjnych, ale szczególnie potrzebuję obecnie używanego systemu init.

Fedora 15 i Ubuntu używają teraz systemd, Ubuntu używa Upstart (domyślnie długi czas do 15.04), podczas gdy inne używają odmian Systemu V.

Mam aplikację, którą piszę, aby być demonem międzyplatformowym. Skrypty inicjujące są generowane dynamicznie na podstawie parametrów, które można przekazać podczas konfiguracji.

To, co chciałbym zrobić, to wygenerowanie skryptu tylko dla konkretnego systemu init, którego używają. W ten sposób skrypt instalacyjny może być uruchamiany rozsądnie bez parametrów jako root, a demon może być „zainstalowany” automatycznie.

Oto co wymyśliłem:

  • Wyszukaj systemd, upstart itp w / bin
  • Porównaj / proc / 1 / comm z systemd, upstart itp
  • Zapytaj użytkownika

Jaki byłby najlepszy sposób, aby to zrobić na wiele platform / platform?

Rodzaj pokrewnych. Czy mogę polegać na bash, aby być na większości * nix, czy jest to zależne od dystrybucji / systemu operacyjnego?

Platformy docelowe:

  • System operacyjny Mac
  • Linux (wszystkie dystrybucje)
  • BSD (wszystkie wersje)
  • Solaris, Minix i inne * nix

1
Aby dodać moje dwa centy, bash nie jest domyślnie instalowany na FreeBSD.
Chinmay Kanchi,

@tjameson, czy znalazłeś bardziej bezpośredni sposób? Szukam tego samego, ale odpowiedzi tutaj są tylko wskazówkami, a nie bezpośrednimi odpowiedziami. W szczególności 1) lokalizacje skryptów do przeszukania i 2) wykrywanie systemu inicjującego w przypadku, gdy zainstalowano wiele z nich (odpowiedź bezpośrednio na bash).
n611x007

3
@naxa - krótka odpowiedź, nie. Długa odpowiedź, z którą możesz dojść dość daleko ps -p 1 -o command(drukuje ścieżkę do prądu init). W Arch Linux i Fedora (IIRC) jest to dowiązanie symboliczne do pliku systemdbinarnego (prawdopodobnie takie samo we wszystkich systemdsystemach). On upstart, init --helpbędzie drukować informacje o użytkowaniu, a na moim polu, upstartjest wymieniony gdzie jest napisane, kto na e-mail. W FreeBSD (sysV) zwróci błąd. Mogą istnieć podobne wskazówki w innych systemach, ale odkąd zadałem to pytanie, postanowiłem po prostu utworzyć je dla wszystkich platform i utworzyć osobne pakiety dla każdego z nich.
beatgammit

dzięki wielkie informacje! Na tej podstawie nauczyłem się, że sudo lsof -a -p 1 -d txtmoże dać jeszcze dokładniejsze wyniki. psmoże wydrukować dowolną nazwę, podczas gdy wraz z lsoftobą uzyskasz prawdziwą ścieżkę wykonywalną. (Zobacz moje pytanie unix.stackexchange.com/questions/102453/… )
n611x007

1
Żadna z odpowiedzi lub komentarzy w połączonym pytaniu nie jest związana z bash. Rozwiązania te powinny mieć zastosowanie również w twojej sprawie.
Marco

Odpowiedzi:


30

Na drugie pytanie odpowiedź brzmi „ nie” i powinieneś rzucić okiem na zasoby dotyczące programowania przenośnych powłok .

Jeśli chodzi o pierwszą część - po pierwsze, z pewnością musisz być ostrożny. Powiedziałbym, aby wykonać kilka testów, aby się upewnić - ponieważ fakt, że ktoś ma zainstalowany systemd (np.), Nie oznacza, że ​​jest on faktycznie używany jako domyślny init. Również patrzenie na to /proc/1/commmoże być mylące, ponieważ niektóre instalacje różnych programów inicjujących mogą automatycznie utworzyć /sbin/initdowiązanie symboliczne lub nawet zmienić nazwę swojego głównego programu.

Być może najbardziej użyteczną rzeczą może być przyjrzenie się typowi skryptów inicjujących - ponieważ są one tym, co faktycznie stworzysz, bez względu na to, co je uruchamia.

Na marginesie, możesz również przyjrzeć się OpenRC, który ma na celu zapewnienie struktury skryptów init, która jest kompatybilna zarówno z systemami Linux, jak i BSD.


2
Co rozumiesz przez „spojrzenie na typ skryptów inicjujących”? Często różne systemy inicjujące umieszczają swoje skrypty / pliki gdzieś poza nimi /etc/init, tak jak systemd je umieszcza /etc/systemd. Gdybym chciał, żeby mój skrypt tego nie sprawdził, może to chwilę potrwać. Aha, i dziękuję za łącze BTW do programowania przenośnych powłok.
beatgammit

1
Chciałem powiedzieć, że niektóre implementacje init można dostosować do różnych typów i lokalizacji skryptów init (takich jak /etc/rc.d/lub /etc/init.d/). I powinieneś właściwie dostosować swój program w czasie instalacji, aby wykorzystać strukturę używaną w danym systemie.
rozcietrzewiacz

2
Czy mówisz, że nie ma niezawodnego sposobu programowego wykrycia systemu init? Posiadanie przez użytkownika parametrów jest z pewnością bezpieczniejsze, ale jeśli użytkownik niczego nie przekaże, jaki byłby najlepszy sposób na odgadnięcie?
beatgammit,

Nie mam pojęcia, jaki będzie najlepszy sposób dla twojego programu - wszystko zależy od tego, jakie systemy skończą. Nie korzystałem z zbyt wielu dystrybucji, ale starałem się podzielić swoimi spostrzeżeniami, aby ci pomóc. Jest to trudny kawałek scenariusza, który próbujesz wypróbować, a ja próbowałem dać ci pewne spojrzenie na pole - sam musisz dojść do ostatecznej odpowiedzi lub poczekać na więcej wskazówek.
rozcietrzewiacz

Fajnie, dziękuję za całą twoją pomoc. Zdecydowanie wskazałeś mi właściwy kierunek.
beatgammit,

58

Sam doszedłem do tego problemu i postanowiłem zrobić kilka testów. W pełni zgadzam się z odpowiedzią, że dla każdej dystrybucji należy spakować osobno, ale czasami istnieją praktyczne problemy, które temu zapobiegają (zwłaszcza siła robocza).

Dla tych, którzy chcą „automatycznie wykryć”, oto, co odkryłem na ograniczonym zestawie dystrybucji (więcej poniżej):

  • Możesz powiedzieć upstart od:

    [[ `/sbin/init --version` =~ upstart ]] && echo yes || echo no
  • Możesz powiedzieć systemd z:

    [[ `systemctl` =~ -\.mount ]] && echo yes || echo no
  • Możesz powiedzieć sys-v init z:

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

Oto moje eksperymenty z następującą linią poleceń:

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

w instancjach ec2 (podaję identyfikator AMI dla US-east):

  • ArchLinux: używa systemd (od 2012.10.06 )
  • CentOS6.4 ami-52009e3b: using upstart
  • CentOS7 ami-96a818fe: using systemd
  • Debian 6 ami-80e915e9: przy użyciu sysv-init
  • Debian 7.5 ami-2c886c44: przy użyciu sysv-init
  • Debian 7.6 GCE container-vm: using sysv-init
  • RHEL 6.5 ami-8d756fe4: przy użyciu upstart
  • SLES 11 ami-e8084981: using sysv-init
  • Ubuntu 10.04 ami-6b350a02: przy użyciu aktualizacji początkowej
  • Ubuntu 12.04 ami-b08b6cd8: using upstart
  • Ubuntu 14.04 ami-a427efcc: using upstart
  • Ubuntu 14.10 i nowsze: za pomocą systemd
  • AWS linux 2014.3.2 ami-7c807d14: przy użyciu upstart
  • Fedora 19 ami-f525389c: przy użyciu systemd
  • Fedora 20 ami-21362b48: przy użyciu systemd

Żeby było jasne: nie twierdzę, że jest to niezawodne! , prawie na pewno nie jest. Zauważ też, że dla wygody używam dopasowań regularnych bash, które nie są dostępne wszędzie. Powyższe jest dla mnie wystarczająco dobre. Jeśli jednak znajdziesz dystrybucję, w której się nie powiedzie, daj mi znać, a ja postaram się to naprawić, jeśli istnieje EC2 AMI, który odtwarza problem ...


5
Zgodnie z dokumentacją systemd ( sd_booted (3) ) poprawnym sposobem sprawdzenia systemd jest sprawdzenie, czy katalog /run/systemd/systemistnieje.
Robie Basak,

1
Dodam do tego wykrywania launchd, system inicjujący na macOS: [[ $(ps 1) =~ 'launchd' ]] && echo yes || echo notestowany na MacBookPro, macOS Sierra Wersja 10.12
Tony

Dodałbym również busybox:if [ -h /sbin/init -a $(readlink /sbin/init | grep busybox | wc -l) -gt 0 ]; then echo yes; else echo no; fi
Astrinus

18

Korzystanie z procesów

Patrząc na wynik kilku pspoleceń, które mogą wykryć różne wersje systemd& upstart, które można by spreparować w następujący sposób:

dorobkiewicz

$ 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

Zwrócenie uwagi na nazwę procesu, jakim jest PID # 1, może również potencjalnie rzucić światło na to, który system inicjujący jest używany. Na Fedorze 19 (która wykorzystuje systemdna przykład:

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

Zauważ, że to nie jest init. Na Ubuntu z Upstart jest nadal /sbin/init.

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

UWAGA: Należy jednak zachować ostrożność. Nie ma w tym nic, co mówi, że określony system inicjujący używany w danej dystrybucji musi mieć systemdPID # 1.

rodzajowy

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

Spójrz na procesy z ppid 1 (potomkami procesu init). (Niektóre) nazwy procesów potomnych mogą wskazywać na używany system init.

System plików

Jeśli przesłuchasz initplik wykonywalny, możesz również uzyskać z niego trochę informacji. Po prostu parsuje --versionwyjście. Na przykład:

dorobkiewicz

$ 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

UWAGA: Fakt, że initnie znajduje się w standardowej lokalizacji, jest trochę podpowiedź / powiedzieć. Zawsze znajduje się w /sbin/initsystemach sysvinit.

sysvinit

$ type init
init is /sbin/init

Także to:

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

Wnioski

Wydaje się więc, że nie ma jednego sposobu, aby to zrobić, ale możesz sformułować zestaw testów, które pozwoliłyby określić, z którego systemu init korzystasz z dość wysokim poziomem pewności.


Co powiesz na:pgrep systemd >/dev/null && echo init system: systemd
Marco

Dziękuję, właśnie tego szukałem: kilka kroków, które należy podjąć, aby spróbować określić system init.
user369450

1
PID # 1 niekoniecznie musi być /usr/lib/systemd/systemdzastosowany w systemie, to fałszywe założenie. Na przykład w moim systemie PID # 1 to /sbin/init(używam systemd). To zależy od dystrybucji.
Marco

Na mojej instalacji kubuntu 15.04 wydaje się, że mam zarówno systemd, jak i sysvinit. Nie wiem dlaczego ani co to znaczy, po prostu mówiąc… pgrep systemd >/dev/null && echo init system: systemd -> init system: systemditype init -> init is /sbin/init
dotnetCarpenter

12

Nie tak wydajne, ale wydaje mi się, że działa.

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

Wydrukuje więcej wierszy, jeśli pasuje więcej niż jeden ciąg, co można przetłumaczyć na „Nie mogę zgadnąć”. Ciągi używane w grep mogą być nieznacznie modyfikowane, ale podczas testowania w następnym systemie zawsze otrzymałem jedną linię.

  • RHEL 6.4 [UPSTART]
  • RHEL ES 4 (Nahant Update 7) [SYSVINIT]
  • Ubuntu 16.04.1 LTS [SYSTEMD]
  • Ubuntu 14.04.2 LTS [UPSTART]
  • Fedora wydanie 23 (powłoka online) [SYSTEMD]
  • Debian GNU / Linux 7 (powłoka online) [SYSTEMD]

Bardziej uproszczone podejście do tego samego rozwiązania (ale zatrzymuje się przy pierwszym meczu)

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

niezła pierwsza odpowiedź. witamy na unix.se!
Olivier Dulac

Właśnie wypróbowałem to na domyślnym obrazie dokera Gentoo z zainstalowanym OpenRC i zwróciło SYSVINIT. Według wiki.gentoo.org/wiki/Comparison_of_init_systems domyślną wersją Gentoo jest OpenRC, ale wygląda na to, że OpenRC używa sysvinit. Kiedy następnie próbuję wykonać polecenia OpenRC, pojawia się komunikat „Próbujesz uruchomić usługę OpenRC w systemie, którego openrc nie uruchomił się”. Czy istnieje sposób na odróżnienie sysvinit właściwego od OpenRC za pomocą sysvinit?
tudor

9

Czasami jest to tak proste, jak użycie ls :

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

Myślę, że jeśli /sbin/initnie jest to symboliczny link, będziesz musiał sprawdzić dalsze poniższe sugestie w innych odpowiedziach.


3
  1. Do tego służą pakiety specyficzne dla dystrybucji. Prawidłowe instalowanie oprogramowania to znacznie więcej niż wykrywanie systemu init. Wiele dystrybucji używa SysVinit, ale nie wszystkie piszą swoje skrypty inicjujące w ten sam sposób. Właściwym sposobem rozwiązania tego jest uwzględnienie wszystkich różnych wariantów, a następnie spakowanie go przy użyciu plików spec z nazwami zależności specyficznymi dla dystrybucji dla dystrybucji rpm, plików deb dla systemów opartych na apt itp. Prawie wszystkie dystrybucje mają jakąś specyfikację pakietu umie pisać, które zawierają zależności, skrypty, skrypty inicjujące itp. Nie wymyślaj tutaj koła na nowo.

  2. Nie. Co sprowadza nas z powrotem do 1. Jeśli potrzebujesz bash, powinna to być zależność. Możesz określić tę kontrolę w ramach skryptów konfiguracyjnych, ale powinna ona również znajdować się w opisach pakietów.

Edycja: użyj flag na skrypcie konfiguracyjnym, takim jak --with upstartlub --without sysvinit. Wybierz rozsądne ustawienie domyślne, a następnie skrypty, które pakują twoje oprogramowanie dla innych dystrybucji, mogą uruchomić to z innymi opcjami.


Hmph, więc wygląda na to, że nie mogę mieć rozwiązania „jeden skrypt, by rządzić nimi wszystkimi”. Widziałem wiele programów, które używają autoconf lub podobnego do obsługi rzeczy międzyplatformowych, ale nie wydaje się, aby było to właściwe narzędzie dla mojej aplikacji. Czy utrzymanie wersji dla każdej platformy jest naprawdę jedynym niezawodnym rozwiązaniem?
beatgammit,

Jednym skryptem instalacyjnym do rządzenia nimi wszystkimi jest BadIdea. Kończy się to niepowodzeniem większej liczby miejsc niż działa. Autoconf jest dobry, o ile to możliwe. Ciężko pracuj nad tym, aby koniec oprogramowania był tak ogólny, jak to możliwe, i dołącz alternatywne skrypty inicjujące do swojego pakietu. Skonfiguruj specyfikacje pakietu dla kilku głównych dystrybucji. Jeśli twoje oprogramowanie jest dobre, możesz poprosić innych ludzi o pomoc w przygotowaniu go na inne systemy.
Caleb

@tjameson: Właśnie zdałem sobie sprawę, że zapomniałem najważniejszego kawałka. Tego rodzaju czynności zwykle wykonuje się za pomocą przełączników przekazanych do skryptu konfiguracji. Procedury kompilacji / pakietów każdej dystrybucji mogą wywoływać różne przełączniki, a twoja konfiguracja / marka musi tylko wiedzieć, który przełącznik został przekazany, a nie wykrywać wszystkich możliwych konfiguracji oprogramowania.
Caleb

@ Caleb- Tak, mam już tę logikę, ale dobry haczyk. Miałem nadzieję, że sposób, by powąchać system init, użyje inteligentnego domysły niż rozsądnego domyślnego.
beatgammit,

2

Na Gentoo spójrz na 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]

Jeśli tak init, to system inicjujący to OpenRC. Jeśli tak systemd, to system inicjujący to systemd.

Możesz wykryć Gentoo za pomocą [ -f /etc/gentoo-release ].

Inną metodą Gentoo jest użycie profile-config show, która pokaże, jaki domyślny profil jest używany. Wszystkie profile oprócz dwóch kończących się na / systemd używają init OpenRC. Należy pamiętać, że są one reprezentatywne tylko dla wartości domyślnych i możliwe jest, że użytkownik podjął kroki w celu zastąpienia tej wartości domyślnej i może nie wskazywać na faktyczne użycie menedżera init.


Głupie pytanie, ale jak mogę sprawdzić pid 1?
Faheem Mitha

Użyj popcji (identycznej z -pi --pid), aby wybrać według PID. Powyższy fragment jest w rzeczywistości wyjściem dla ps u --pid 1.
José M. Benítez

2

Na debian / sbin / init znajduje się dowiązanie symboliczne do twojego domyślnego init

ls -l /sbin/init

poda informacje, których szukasz.

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

1
Skąd. W Ubuntu 14.04 z Upstart nie jest to dowiązanie symboliczne.
muru,

Zainstaluj inny system init i sprawdź ponownie.
rmorelli74,

A który inny initmogę zainstalować na Ubuntu 14.04?
muru

... dlaczego nie sysv lub systemd?
rmorelli74,

1
Nie chcę głosować, chcę tylko, abyś określił, której wersji Debiana dotyczy. (Być może sformułowanie „oparte na Debianie” należy
zmienić

2

Samo włączenie się w proces z PID 1 powie ci:

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

Nie wszystkie wymienione OSeS mają procsystem plików ...
Toby Speight,

2

Pomocne może być również sprawdzenie deskryptorów plików. I pochodzi z faktycznego uruchomienia init (obecnie Debian pozwala na zainstalowanie większej liczby systemów 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

Prawdopodobnie bezpieczniejszym sposobem na sprawdzenie zajętości jest check /proc/1/exe, ponieważ zajęty zwykle używa dowiązań symbolicznych:

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

Więc sprawdź może być:

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

Również systemy z systememd zwykle mają katalog /run/systemd/system.
pevik

2

Nie wiem o innych systemach niż Debian (wheezy) / lub Ubuntu (14.10.), Ale takie problemy testuję zwykłym starym filepoleceniem.

file /sbin/init

daj to:

/sbin/init: symbolic link to 'upstart'

Systemy Debian z systemd(np. Sid) pokazują to:

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

Na jakim systemie testowałeś to? Nie ma czegoś takiego jak Debian / Ubuntu, a to nie działa na Debianie. Czy wypróbowałeś to na Ubuntu?
terdon

Przepraszam za to zamieszanie, mam na myśli Debiana (wheezy) / lub Ubuntu (14.10.). Dane wyjściowe 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 oznacza, że ​​używamy SYSV tutaj. Dane wyjściowe dotyczące Ubuntu pokazano w mojej odpowiedzi.
zzeroo

Dokładnie, więc twoje rozwiązanie wydaje się działać tylko wtedy, gdy ktoś używa Upstart i Ubuntu.
terdon

@terdon: W systemach (RHEL, Fedora) z systemem systemd zwraca „symboliczny link do ... systemd”; w systemach (Ubuntu) działających w trybie upstart zwraca „symboliczny link do upstart”; w systemach (RHEL, Ubuntu, Debian) z uruchomioną inicjalizacją SysV init zwraca wartość „wykonywalną”. Chociaż nie jest to wyczerpująca ankieta, a ta metoda najwyraźniej nie jest w 100% niezawodna, jest wyraźnie bliższa „działa na przynajmniej głównych dystrybucjach” niż „tylko na starcie i Ubuntu”!
psmears,

1
@psmears, jeśli działa również w przypadku niektórych systemów systemowych, jest to rzeczywiście lepsze (ale nie wspomniane w tej odpowiedzi). Właśnie przetestowałem na Debianie z systemem sysvinit i trzema Ubuntus (10.04,12.04 i 14.04, wszystkie działające na starcie) i zwróciłem file /sbin/init„wykonywalny” na wszystkich systemach. Zwraca również to samo na CentOS 5.8, SLES 10, Ubuntu 8.04, w zasadzie na każdym systemie, który mogę zdobyć. Tak więc, o ile mogę powiedzieć, nie działa nawet dla upstart i Ubuntu.
terdon

2

Miałem również ten sam problem i wykonałem wiele testów na niektórych maszynach RedHat / CentOS / Debian / Ubuntu / Mint. Właśnie z tym skończyłem, z dobrymi wynikami.

  1. Znajdź nazwę pliku wykonywalnego za pomocą PID 1:

    ps -p 1

    Jeśli jest to systemd lub Upstart, problem został rozwiązany. Jeśli jest to „init”, może to być dowiązanie symboliczne lub coś innego niż nazwa początkowa. Śmiało.

  2. Znajdź prawdziwą ścieżkę do pliku wykonywalnego (działa tylko jako root):

    ls -l `which init`

    Jeśli initjest dowiązaniem symbolicznym do Upstart lub systemd, problem został rozwiązany. W przeciwnym razie jest prawie pewne, że masz init SysV. Ale może to być źle nazwany plik wykonywalny. Śmiało.

  3. Znajdź pakiet, który udostępnia plik wykonywalny. Niestety jest to zależne od dystrybucji:

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

Następnie, jeśli chcesz napisać skrypt (najśmieszniejsza część, IMHO), to są moje jednowierszowe (uruchamiane jako 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
Nie wszystkie określone systemy operacyjne mają dpkg lub rpm (ten problem nie dotyczy tylko twojej odpowiedzi, BTW).
Toby Speight

@ toby-speight Tak, jasne. Uwaga: Stwierdziłem to w mojej odpowiedzi, aby wyjaśnić ograniczenie.
Emerson Prado

Jeśli chodzi o krok 3, możesz uruchomić, init --versionaby uzyskać informacje.
jarno

1

To jest naprawdę łatwe dla niektórych systemów init. Dla systemd:

test -d /run/systemd/system

dla upstart:

initctl --version | grep -q upstart

cokolwiek innego, możesz po prostu założyć na podstawie dystrybucji (uruchomionej na OS X, sysvinit na Debianie, OpenRC na Gentoo).


„zakładanie na podstawie dystrybucji” nie działa w Debianie, w którym obsługiwane są co najmniej trzy różne elementy…
Toby Speight

1

Oto skrypt bash do wykrycia. W tej chwili sprawdza tylko dostępność i system, ale powinna być łatwa do rozszerzenia. Wziąłem to z kodu, który włączyłem do skryptu instalacyjnego sterownika 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
Myślę, że użycie tego /procwiąże się z Linuksem (jeśli jest odpowiednio skonfigurowane) i jednym lub dwoma innymi - z pewnością nie jest uniwersalne.
Toby Speight

1

Istnieje wiele problemów związanych z kompatybilnością podczas testowania systemd vs initd. To faktycznie działa na OpenSuSE 42.1:ps --pid 1 | grep -q systemd && echo 'systemd' || echo 'init'


1

Dla systemd:

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

oddawanie głosu, ponieważ ta odpowiedź nie zawiera żadnych nowych lub innych informacji w porównaniu z wieloma istniejącymi odpowiedziami.
jayhendren

@jayhendren Nie widzę tego fragmentu w innym miejscu. To nie jest kompletne samo w sobie, i prawdopodobnie lepiej byłoby wypowiedzieć się w odpowiedzi na odpowiedź unix.stackexchange.com/a/164092/100397 autor: TvE
roaima

Och, masz rację @roaima. To nie jest dokładnie to samo co inne. Przeszukałem stronę w celu
znalezienia niezbyt

1
To chyba najbardziej poprawna odpowiedź :)
Jack O'Connor,

1

Moje rozwiązanie: sprawdź polecenie uruchomione jako proces o identyfikatorze 1.

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

W tej chwili mam dostęp tylko do maszyn Init i SystemD, więc nie mogę powiedzieć, jak zostanie wykryty Upstart lub macOS (OS X), ale będę szukał dalej.


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
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.