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
źródło
ps -p 1 -o command
(drukuje ścieżkę do prąduinit
). W Arch Linux i Fedora (IIRC) jest to dowiązanie symboliczne do plikusystemd
binarnego (prawdopodobnie takie samo we wszystkichsystemd
systemach). Onupstart
,init --help
będzie drukować informacje o użytkowaniu, a na moim polu,upstart
jest 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.sudo lsof -a -p 1 -d txt
może dać jeszcze dokładniejsze wyniki.ps
może wydrukować dowolną nazwę, podczas gdy wraz zlsof
tobą uzyskasz prawdziwą ścieżkę wykonywalną. (Zobacz moje pytanie unix.stackexchange.com/questions/102453/… )Odpowiedzi:
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/comm
może być mylące, ponieważ niektóre instalacje różnych programów inicjujących mogą automatycznie utworzyć/sbin/init
dowią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.
źródło
/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./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.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:
Możesz powiedzieć systemd z:
Możesz powiedzieć sys-v init z:
Oto moje eksperymenty z następującą linią poleceń:
w instancjach ec2 (podaję identyfikator AMI dla US-east):
Ż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 ...
źródło
/run/systemd/system
istnieje.launchd
, system inicjujący na macOS:[[ $(ps 1) =~ 'launchd' ]] && echo yes || echo no
testowany na MacBookPro, macOS Sierra Wersja 10.12if [ -h /sbin/init -a $(readlink /sbin/init | grep busybox | wc -l) -gt 0 ]; then echo yes; else echo no; fi
Korzystanie z procesów
Patrząc na wynik kilku
ps
poleceń, które mogą wykryć różne wersjesystemd
&upstart
, które można by spreparować w następujący sposób:dorobkiewicz
systemd
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
systemd
na przykład:Zauważ, że to nie jest
init
. Na Ubuntu z Upstart jest nadal/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ć
systemd
PID # 1.rodzajowy
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
init
plik wykonywalny, możesz również uzyskać z niego trochę informacji. Po prostu parsuje--version
wyjście. Na przykład:dorobkiewicz
systemd
UWAGA: Fakt, że
init
nie znajduje się w standardowej lokalizacji, jest trochę podpowiedź / powiedzieć. Zawsze znajduje się w/sbin/init
systemach sysvinit.sysvinit
Także to:
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.
źródło
pgrep systemd >/dev/null && echo init system: systemd
/usr/lib/systemd/systemd
zastosowany 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.pgrep systemd >/dev/null && echo init system: systemd -> init system: systemd
itype init -> init is /sbin/init
Nie tak wydajne, ale wydaje mi się, że działa.
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ę.
Bardziej uproszczone podejście do tego samego rozwiązania (ale zatrzymuje się przy pierwszym meczu)
źródło
Czasami jest to tak proste, jak użycie
ls
:Myślę, że jeśli
/sbin/init
nie jest to symboliczny link, będziesz musiał sprawdzić dalsze poniższe sugestie w innych odpowiedziach.źródło
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.
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 upstart
lub--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.źródło
Na Gentoo spójrz na pid 1:
Jeśli tak
init
, to system inicjujący toOpenRC
. Jeśli taksystemd
, to system inicjujący tosystemd
.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.źródło
p
opcji (identycznej z-p
i--pid
), aby wybrać według PID. Powyższy fragment jest w rzeczywistości wyjściem dlaps u --pid 1
.Na debian / sbin / init znajduje się dowiązanie symboliczne do twojego domyślnego init
poda informacje, których szukasz.
źródło
init
mogę zainstalować na Ubuntu 14.04?Samo włączenie się w proces z PID 1 powie ci:
źródło
proc
system plików ...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) :-)
Prawdopodobnie bezpieczniejszym sposobem na sprawdzenie zajętości jest
check /proc/1/exe
, ponieważ zajęty zwykle używa dowiązań symbolicznych:Więc sprawdź może być:
źródło
/run/systemd/system
.Nie wiem o innych systemach niż Debian (wheezy) / lub Ubuntu (14.10.), Ale takie problemy testuję zwykłym starym
file
poleceniem.daj to:
Systemy Debian z
systemd
(np. Sid) pokazują to:źródło
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.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.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.
Znajdź nazwę pliku wykonywalnego za pomocą PID 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.
Znajdź prawdziwą ścieżkę do pliku wykonywalnego (działa tylko jako root):
Jeśli
init
jest 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.Znajdź pakiet, który udostępnia plik wykonywalny. Niestety jest to zależne od dystrybucji:
Następnie, jeśli chcesz napisać skrypt (najśmieszniejsza część, IMHO), to są moje jednowierszowe (uruchamiane jako root):
źródło
init --version
aby uzyskać informacje.To jest naprawdę łatwe dla niektórych systemów init. Dla systemd:
dla upstart:
cokolwiek innego, możesz po prostu założyć na podstawie dystrybucji (uruchomionej na OS X, sysvinit na Debianie, OpenRC na Gentoo).
źródło
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 .
źródło
/proc
wiąże się z Linuksem (jeśli jest odpowiednio skonfigurowane) i jednym lub dwoma innymi - z pewnością nie jest uniwersalne.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'
źródło
Dla
systemd
:źródło
Moje rozwiązanie: sprawdź polecenie uruchomione jako proces o identyfikatorze 1.
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.
źródło
źródło