Rileva il sistema init usando la shell


90

Questo potrebbe avere più a che fare con il rilevamento di sistemi operativi, ma ho bisogno in particolare del sistema init attualmente in uso sul sistema.

Fedora 15 e Ubuntu ora usano systemd, Ubuntu usava Upstart (impostazione predefinita da molto tempo fino al 15.04), mentre altri usano varianti di System V.

Ho un'applicazione che sto scrivendo per essere un demone multipiattaforma. Gli script init vengono generati dinamicamente in base a parametri che possono essere passati su configure.

Quello che mi piacerebbe fare è solo generare lo script per il particolare sistema init che stanno usando. In questo modo lo script di installazione può essere eseguito ragionevolmente senza parametri come root e il demone può essere "installato" automagicamente.

Questo è quello che ho escogitato:

  • Cerca systemd, upstart, ecc. In / bin
  • Confronta / proc / 1 / comm con systemd, upstart, ecc
  • Chiedi all'utente

Quale sarebbe il miglior modo cross / platform per farlo?

Tipo di relazione, posso dipendere da bash per essere sulla maggior parte di * nix o dipende dalla distribuzione / dal sistema operativo?

Piattaforme target:

  • Mac OS
  • Linux (tutte le distribuzioni)
  • BSD (tutte le versioni)
  • Solaris, Minix e altri * nix

1
Solo per aggiungere i miei due centesimi, bash non è installato di default su FreeBSD.
Chinmay Kanchi,

@tjameson, hai trovato un modo più diretto? Sto cercando la stessa cosa, ma le risposte qui sono solo indicazioni, non risposte dirette. In particolare 1) posizioni degli script da cercare e 2) rilevamento effettivo del sistema init, nel caso ce ne siano più installati (bash ha ricevuto risposta direttamente).
n611x007,

3
@naxa - Risposta breve, no. Risposta lunga, puoi andare abbastanza lontano con ps -p 1 -o command(stampa il percorso alla corrente init). Su Arch Linux e Fedora (IIRC), è un collegamento simbolico al systemdbinario (probabilmente lo stesso su tutti i systemdsistemi). Su upstart, init --helpstamperà le informazioni sull'utilizzo e sulla mia scatola upstartviene menzionato dove si dice chi deve inviare un'e-mail. Su FreeBSD (sysV), questo restituirà un errore. Potrebbero esserci indizi simili su altri sistemi, ma da quando ho posto questa domanda, ho deciso di crearli per tutte le piattaforme e creare pacchetti separati per ognuno.
beatgammit,

grazie grandi informazioni! Saltando da quello che ho imparato che sudo lsof -a -p 1 -d txtpuò dare risultati ancora più esatti. pspuò stampare un nome arbitrario, mentre con lsofte otterrai il vero percorso eseguibile. (Vedi la mia domanda unix.stackexchange.com/questions/102453/… )
n611x007

1
Nessuna delle risposte o dei commenti nella domanda collegata è correlata a bash. Le soluzioni dovrebbero essere applicabili anche al tuo caso.
Marco,

Risposte:


30

Per la seconda domanda, la risposta è no e dovresti dare un'occhiata a Risorse per la programmazione della shell portatile .

Per quanto riguarda la prima parte - prima di tutto, devi certamente stare attento. Direi di eseguire diversi test per essere sicuri - perché il fatto che qualcuno abbia systemd (per esempio) installato, non significa che sia effettivamente utilizzato come predefinito init. Inoltre, guardare /proc/1/commpuò essere fuorviante, perché alcune installazioni di vari programmi init possono creare automaticamente /sbin/initun collegamento simbolico o anche una versione rinominata del loro programma principale.

Forse la cosa più utile potrebbe essere guardare il tipo di script init - perché quelli sono ciò che creerai, indipendentemente da ciò che li esegue.

Come nota a margine , potresti anche dare un'occhiata a OpenRC che mira a fornire una struttura di script init compatibile con i sistemi Linux e BSD.


2
Cosa intendi con "guarda il tipo di script init"? Spesso diversi sistemi init mettono i loro script / file da qualche parte /etc/init, come systemd li inserisce /etc/systemd. Se dovessi fare in modo che la mia sceneggiatura li scriva, potrebbe volerci un po 'di tempo. Oh, e grazie per il collegamento BTW per la programmazione della shell portatile.
beatgammit,

1
Intendevo dire che alcune implementazioni di init possono essere adattate per usare tipi e posizioni di script di init diversi (come /etc/rc.d/o /etc/init.d/). E dovresti adattare correttamente il tuo programma al momento dell'installazione per utilizzare la struttura che viene utilizzata su un determinato sistema.
rozcietrzewiacz,

2
Quindi, stai dicendo che non esiste un modo affidabile per rilevare il sistema init a livello di codice? Avere l'utente che passa i parametri è sicuramente più sicuro, ma se l'utente non passa nulla, quale sarebbe il modo migliore per indovinare?
Beatgammit,

Non ho idea di quale sarà il modo migliore per il tuo programma - tutto dipende da quali sistemi finirà per funzionare. Non ho usato troppe distribuzioni, ma stavo cercando di condividere le mie osservazioni per aiutarti. È un duro scripting che stai per provare e ho provato a darti un po 'di vista sul campo: devi arrivare tu stesso alla risposta finale o attendere ulteriori suggerimenti.
rozcietrzewiacz,

Bene, grazie per tutto il tuo aiuto. Mi hai decisamente indicato la giusta direzione.
Beatgammit,

58

Ho affrontato questo problema da solo e ho deciso di fare alcuni test. Concordo pienamente con la risposta che si dovrebbe impacchettare separatamente per ciascuna distro, ma a volte ci sono problemi pratici che lo impediscono (non ultimo il personale).

Quindi per coloro che vogliono "rilevare automaticamente" ecco cosa ho scoperto in un set limitato di distro (più sotto):

  • Puoi iniziare a partire da:

    [[ `/sbin/init --version` =~ upstart ]] && echo yes || echo no
  • Puoi dire a systemd da:

    [[ `systemctl` =~ -\.mount ]] && echo yes || echo no
  • Puoi dire a sys-v init da:

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

Ecco i miei esperimenti con la seguente riga di comando:

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

su istanze ec2 (includo l'id AMI us-est):

  • ArchLinux: using systemd (dal 2012.10.06 )
  • CentOS6.4 ami-52009e3b: usando upstart
  • CentOS7 ami-96a818fe: usando systemd
  • Debian 6 ami-80e915e9: usando sysv-init
  • Debian 7.5 ami-2c886c44: usando sysv-init
  • Debian 7.6 GCE container-vm: usando sysv-init
  • RHEL 6.5 ami-8d756fe4: usando upstart
  • SLES 11 ami-e8084981: usando sysv-init
  • Ubuntu 10.04 ami-6b350a02: usando upstart
  • Ubuntu 12.04 ami-b08b6cd8: usando upstart
  • Ubuntu 14.04 ami-a427efcc: usando upstart
  • Ubuntu 14.10 e successivi: usando systemd
  • AWS linux 2014.3.2 ami-7c807d14: usando upstart
  • Fedora 19 ami-f525389c: usando systemd
  • Fedora 20 ami-21362b48: usando systemd

Giusto per essere chiari: non sto affermando che questo è infallibile! , quasi certamente non lo è. Inoltre, per comodità, utilizzo le partite di rehexp bash, che non sono disponibili ovunque. Quanto sopra è abbastanza buono per me in questo momento. Tuttavia, se trovi una distro in cui non funziona, faccelo sapere e proverò a risolverlo se esiste un AMI EC2 che riproduce il problema ...


5
Secondo la documentazione di systemd ( sd_booted (3) ), il modo corretto di verificare systemd è verificare l' /run/systemd/systemesistenza della directory .
Robie Basak,

1
Aggiungerò a questo rilevamento launchdil sistema init su macOS: [[ $(ps 1) =~ 'launchd' ]] && echo yes || echo notestato su MacBookPro, macOS Sierra Versione 10.12
Tony

Vorrei anche aggiungere busybox:if [ -h /sbin/init -a $(readlink /sbin/init | grep busybox | wc -l) -gt 0 ]; then echo yes; else echo no; fi
Astrinus il

18

Utilizzando i processi

Guardando l'output da un paio di pscomandi in grado di rilevare le varie versioni di systemd& upstart, che potrebbero essere realizzate in questo modo:

parvenu

$ 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

Prestare attenzione al nome del processo PID n. 1 può anche far luce su quale sistema init viene utilizzato. Su Fedora 19 (che utilizza systemd, ad esempio:

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

Si noti che non lo è init. Su Ubuntu con Upstart è ancora /sbin/init.

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

NOTA: ma usalo con un po 'di cautela. Non c'è nulla in pietra che dica che un particolare sistema init usato su una data distro deve avere systemdcome PID # 1.

generico

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

Guarda i processi con ppid 1 (figli del processo init). (Alcuni dei) nomi di processi secondari potrebbero indicare il sistema init in uso.

Il filesystem

Se si interroga l' initeseguibile, è possibile ottenere anche alcune informazioni da esso. Analizzando semplicemente l' --versionoutput. Per esempio:

parvenu

$ 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

NOTA: il fatto che initnon si trovi nella sua posizione standard è un po 'di un suggerimento. Si trova sempre nei /sbin/initsistemi sysvinit.

sysvinit

$ type init
init is /sbin/init

Anche questo:

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

conclusioni

Quindi non sembra esserci un modo per farlo, ma potresti formulare una serie di controlli che individuerebbero quale sistema di inizializzazione stai usando con un livello di sicurezza abbastanza elevato.


Che ne dici di:pgrep systemd >/dev/null && echo init system: systemd
Marco,

Grazie, questo è esattamente quello che stavo cercando: alcuni passi da fare per provare a determinare il sistema init.
user369450,

1
Il PID n. 1 non è necessariamente /usr/lib/systemd/systemdse viene utilizzato systemd, è un presupposto falso. Sul mio sistema, ad esempio, PID # 1 è /sbin/init(io uso systemd). Dipende dalla distribuzione.
Marco,

Nella mia installazione di Kubuntu 15.04 mi sembra di avere sia systemd che sysvinit. Non so perché o cosa significhi solo dire .. pgrep systemd >/dev/null && echo init system: systemd -> init system: systemdetype init -> init is /sbin/init
dotnetCarpenter il

12

Non così efficiente, ma sembra che funzioni.

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

Stamperà più righe se corrispondono più di una stringa, che potrebbe essere tradotta in "Impossibile indovinare". Le stringhe utilizzate in grep potrebbero essere leggermente modificate, ma quando sono state testate nel seguente sistema operativo ho sempre ottenuto una riga.

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

Un approccio più semplicistico della stessa soluzione (ma si ferma alla prima partita)

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

bella prima risposta. benvenuto su unix.se!
Olivier Dulac,

Ho appena provato questo su un'immagine docker predefinita di Gentoo con OpenRC installato e ha restituito SYSVINIT. Secondo wiki.gentoo.org/wiki/Comparison_of_init_systems il valore predefinito per Gentoo è OpenRC, ma sembra che OpenRC utilizzi sysvinit. Quando provo quindi i comandi OpenRC ottengo "Stai tentando di eseguire un servizio OpenRC su un sistema che openrc non ha avviato." C'è un modo per distinguere tra sysvinit proprio e OpenRC usando sysvinit?
Tudor

9

A volte è facile come usare ls :

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

Suppongo che se /sbin/initnon è un link simbolico, dovrai controllare ulteriori suggerimenti seguenti in altre risposte.


3
  1. Ecco a cosa servono i pacchetti specifici per la distribuzione. C'è molto di più per installare correttamente il software oltre a rilevare il sistema init. Molte distribuzioni usano SysVinit ma non tutte scrivono i loro script init allo stesso modo. Il modo corretto per risolvere questo problema è includere tutte le diverse varianti e quindi raggrupparle usando file di specifiche con nomi di dipendenza specifici della distro per distribuzioni rpm, file deb per sistemi basati su apt, ecc. Quasi tutte le distro hanno una sorta di specifica del pacchetto può scrivere che include dipendenze, script, script init, ecc. Non reinventare la ruota qui.

  2. No. Il che ci riporta a 1. Se hai bisogno di bash dovrebbe essere una dipendenza. È possibile specificare questo controllo come parte degli script di configurazione, ma dovrebbe anche essere nelle descrizioni dei pacchetti.

Modifica: usa flag sul tuo script di configurazione come --with upstarto --without sysvinit. Scegli un valore predefinito sano, quindi gli script che impacchettano il tuo software per altre distro possono scegliere di eseguirlo con altre opzioni.


Hmph, quindi sembra che non possa avere una soluzione "uno script per domarli tutti". Ho visto molti programmi che usano autoconf o simili per gestire cose multipiattaforma, ma non sembra che sia lo strumento giusto per la mia applicazione. Il mantenimento delle versioni per ciascuna piattaforma è davvero l'unica soluzione affidabile?
Beatgammit,

Uno script di installazione per domarli tutti è BadIdea. Finisce per fallire più posti di quanti funzioni. Autoconf è buono per quanto va. Lavorare sodo per mantenere la fine del software il più generica possibile e includere script init alternativi nel pacchetto. Specifiche del pacchetto di installazione per diverse distro principali. Se il tuo software è buono, puoi convincere altre persone a darti una mano a comprarlo per altri sistemi.
Caleb,

@tjameson: ho appena realizzato di aver dimenticato la parte più importante. Questo genere di cose viene di solito fatto con le opzioni passate allo script di configurazione. Le routine di compilazione / pacchetto di ogni distro possono chiamare switch diversi e il tuo configure / make deve solo sapere quale switch è stato passato, non rilevare tutte le possibili configurazioni software.
Caleb,

@ Caleb- Sì, ho già quella logica lì dentro, ma buona cattura. Speravo in un modo per annusare il sistema init per usare un'ipotesi intelligente di un default sano.
Beatgammit,

2

Su Gentoo, dai un'occhiata a 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]

Se lo è init, allora è il sistema init OpenRC. Se lo è systemd, allora è il sistema init systemd.

Puoi rilevare Gentoo con [ -f /etc/gentoo-release ].

Un altro metodo su Gentoo è usare profile-config show, che mostrerà quale profilo predefinito è in uso. Tutti i profili tranne i due che terminano in / systemd utilizzano l'init OpenRC. Tieni presente che questi sono solo rappresentativi di un valore predefinito ed è possibile che l'utente abbia adottato delle misure per sovrascrivere tale valore predefinito e potrebbe non essere indicativo della mangiatoia init attualmente in uso.


Domanda stupida, ma come posso verificare il pid 1?
Faheem Mitha,

Utilizzare l' popzione (identica a -pe --pid) per selezionare tramite PID. Lo snippet sopra è in realtà l'output per ps u --pid 1.
José M. Benítez,

2

Su debian / sbin / init è presente un link simbolico al tuo init predefinito

ls -l /sbin/init

ti darà le informazioni che stai cercando.

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

1
Non così. Su Ubuntu 14.04 con Upstart, non è un collegamento simbolico.
Muru,

Installare un altro sistema init e ricontrollare.
rmorelli74,

E quale altro initposso installare su Ubuntu 14.04?
Muru,

... perché non sysv o systemd?
rmorelli74,

1
Non voglio sottovalutare, voglio solo che tu specifichi a quale versione di Debian è applicabile. (E forse riformulare solo "Debian-based" in "Debian", in modo che diventi corretto.)
muru,

2

Semplicemente entrare nel processo con PID 1 ti dirà:

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

Non tutti gli OSe menzionati hanno un procfilesystem ...
Toby Speight,

2

Anche l'ispezione dei descrittori di file può aiutare. Ed è effettivamente eseguendo init (il tratto Debian attualmente consente di avere più sistemi init installati) :-)

$ 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

Probabilmente il modo più sicuro per verificare la presenza di busybox sarebbe check /proc/1/exe, dato che busybox di solito utilizza collegamenti simbolici:

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

Quindi il controllo potrebbe essere:

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

Anche i sistemi con systemd di solito hanno directory /run/systemd/system.
pevik,

2

Non conosco altri sistemi oltre a Debian (wheezy) / o Ubuntu (14.10.) Ma collaudo tali problemi con il semplice vecchio filecomando.

file /sbin/init

dare questo:

/sbin/init: symbolic link to 'upstart'

I sistemi Debian con systemd(es. Sid) mostrano questo:

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

Su quale sistema lo hai provato? Non esiste Debian / Ubuntu e questo non funziona su Debian. L'hai provato su Ubuntu?
terdon

Scusate per questa confusione, intendo Debian (wheezy) / o Ubuntu (14.10.). Output su 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 significa che qui utilizziamo SYSV. L'output per Ubuntu è mostrato nella mia risposta.
zzeroo,

Esatto, quindi la tua soluzione sembra funzionare solo se si utilizza upstart e Ubuntu.
terdon

@terdon: sui sistemi (RHEL, Fedora) che eseguono systemd, restituisce "link simbolico a ... systemd"; sui sistemi (Ubuntu) che eseguono il riavvio restituisce "collegamento simbolico al riavvio"; sui sistemi (RHEL, Ubuntu, Debian) che eseguono SysV init restituisce "eseguibile". Anche se questo non è un sondaggio completo, e questo metodo non è chiaramente sicuro al 100%, è chiaramente molto più vicino a "funziona almeno per le maggiori distro" piuttosto che "solo upstart e Ubuntu"!
psmears,

1
@psmears se funziona anche con alcuni sistemi systemd, è davvero meglio (ma non menzionato in questa risposta). Ho appena testato su un Debian con sistema operativo sysvinit e tre Ubuntus (10.04,12.04 e 14.04, tutti in esecuzione in avvio) e ho file /sbin/initrestituito "eseguibile" su tutti i sistemi. Restituisce lo stesso anche su CentOS 5.8, SLES 10, Ubuntu 8.04, praticamente ogni singolo sistema su cui riesco a mettere le mani. Quindi, per quanto posso dire, non funziona nemmeno per l'avvio e Ubuntu.
terdon

2

Ho avuto anche lo stesso problema e ho fatto molti test su alcune macchine RedHat / CentOS / Debian / Ubuntu / Mint. Questo è quello che ho finito con buoni risultati.

  1. Trova il nome dell'eseguibile con PID 1:

    ps -p 1

    Se è systemd o Upstart, problema risolto. Se è "init", potrebbe essere un collegamento simbolico o qualcosa di diverso da un nome iniziale. Vai avanti.

  2. Trova il percorso reale per l'eseguibile (funziona solo come root):

    ls -l `which init`

    Se initè un collegamento simbolico a Upstart o systemd, problema risolto. Altrimenti, è quasi certo che tu abbia SysV init. Ma può essere un eseguibile errato. Vai avanti.

  3. Trova il pacchetto che fornisce l'eseguibile. Sfortunatamente, questo è distro-dipendente:

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

Quindi, se vuoi copiarlo (la parte più divertente, IMHO), questi sono i miei one-liner (esegui come 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
Non tutti i sistemi operativi specificati hanno dpkg o rpm (questo problema non è specifico solo per la tua risposta, BTW).
Toby Speight,

@ toby-speight Sì, certo. Nota che l'ho dichiarato nella mia risposta, solo per chiarire la limitazione.
Emerson Prado,

Per quanto riguarda il passaggio 3, è possibile eseguire init --versionper ottenere le informazioni.
jarno,

1

Questo è davvero facile per alcuni sistemi init. Per systemd:

test -d /run/systemd/system

per iniziare:

initctl --version | grep -q upstart

per qualsiasi altra cosa, puoi semplicemente supporre in base alla distro (lanciato su OS X, sysvinit su Debian, OpenRC su Gentoo).


"assume in base alla distro" non funziona per Debian, dove sono supportati almeno tre diversi init ...
Toby Speight

1

Ecco uno script bash per eseguire il rilevamento. Controlla solo upstart e systemd al momento, ma dovrebbe essere facile da estendere. Ho preso questo dal codice che ho contribuito allo script di installazione del driver 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
Penso che l'uso di /proclegami questo con Linux (se opportunamente configurato) e uno o due altri - è certamente tutt'altro che universale.
Toby Speight,

1

Esistono molte insidie ​​sulla compatibilità durante il test di systemd vs initd. Questo funziona su OpenSuSE 42.1:ps --pid 1 | grep -q systemd && echo 'systemd' || echo 'init'


1

Per systemd:

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

downvoting perché questa risposta non fornisce alcuna informazione nuova o diversa rispetto alle numerose risposte esistenti.
Jayhendren,

@jayhendren Non vedo questo frammento altrove. Non è completo in sé, e probabilmente sarebbe meglio commentare la risposta unix.stackexchange.com/a/164092/100397 di TvE
roaima,

Oh hai ragione @roaima. Non è esattamente lo stesso degli altri. Ho cercato nella pagina una stringa non troppo specifica :)
jayhendren,

1
Questa sembra essere di gran lunga la risposta più corretta :)
Jack O'Connor,

1

La mia soluzione: controlla il comando in esecuzione come processo con 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

Al momento ho accesso solo alle macchine Init e SystemD, quindi non posso dire come verranno rilevati Upstart o macOS (OS X), ma continuerò a cercare.


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
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.