シェルを使用してinitシステムを検出する


90

これは、オペレーティングシステムの検出に関連している可能性がありますが、特にシステムで現在使用されているinitシステムが必要です。

Fedora 15とUbuntuはsystemdを使用するようになり、UbuntuはUpstart(15.04までの長いデフォルト)を使用していましたが、他のものはSystem Vのバリエーションを使用しています。

クロスプラットフォームデーモンになるために書いているアプリケーションがあります。初期化スクリプトは、configureで渡すことができるパラメーターに基づいて動的に生成されています。

私がやりたいのは、彼らが使用している特定のinitシステム用のスクリプトを生成することです。これにより、インストールスクリプトをrootとしてパラメーターなしで合理的に実行でき、デーモンを自動的に「インストール」できます。

これは私が思いついたものです:

  • / binでsystemd、upstartなどを検索します
  • / proc / 1 / commをsystemd、upstartなどと比較します
  • ユーザーに尋ねる

これを行う最良のクロス/プラットフォーム方法は何でしょうか?

関連の種類、大部分の* nixにbashを依存させることできますか、それともディストリビューション/ OSに依存しますか?

対象プラットフォーム:

  • マックOS
  • Linux(すべてのディストリビューション)
  • BSD(すべてのバージョン)
  • Solaris、Minix、およびその他の* nix

1
2セントを追加するだけで、bashはデフォルトではFreeBSDにインストールされません。
Chinmay Kanchi

@tjameson、もっと直接的な方法を見つけましたか?私は同じことを探していますが、ここでの答えは単なる指示であり、直接的な答えではありません。特に、1)検索するスクリプトの場所、2)複数のシステムがインストールされている場合(bashに直接回答した場合)に有効なinitシステムを検出します。
n611x007

3
@naxa-短い答え、いいえ。長い答え、あなたはかなり遠くまで行くことができますps -p 1 -o command(現在のパスを表示しますinit)。Arch LinuxおよびFedora(IIRC)では、systemdバイナリへのシンボリックリンクです(おそらくすべてのsystemdシステムで同じです)。でupstartinit --help使用情報を印刷upstartします。私のボックスには、誰にメールを送信するかが記載されています。FreeBSD(sysV)では、これはエラーを返します。他のシステムにも同様の手がかりがあるかもしれませんが、この質問を聞いてから、すべてのプラットフォーム用にそれらを作成し、それぞれに個別のパッケージを作成することにしました。
beatgammit

素晴らしい情報ありがとう!それを期待して、sudo lsof -a -p 1 -d txtより正確な結果が得られることを学びました。ps任意の名前を出力lsofする場合がありますが、実際の実行可能パスを取得できます。(私の質問unix.stackexchange.com/questions/102453/…を参照)
n611x007

1
リンクされた質問の回答またはコメントは、bashに関連していません。ソリューションは、あなたのケースにも適用できるはずです。
マルコ14

回答:


30

2番目の質問に対する答えは「いいえ」です。ポータブルシェルプログラミングのリソースを参照してください。

最初の部分については-まず第一に、あなたは確かに注意する必要があります。確認するためにいくつかのテストを実行すると言います。誰か systemd(たとえば)をインストールしたという事実は、実際にデフォルトとして使用されるという意味ではないからですinit。また、/proc/1/commさまざまなinitプログラムをインストール/sbin/initすると、メインプログラムのシンボリックリンクまたは名前を変更したバージョンを自動的に作成できるため、見ていると誤解を招く可能性があります。

たぶん最も便利なのは、initスクリプトの種類を確認することです。なぜなら、それらが実際に作成されるのは、何を実行するかに関係ないからです。

副次的な注意事項として、LinuxシステムとBSDシステムの両方と互換性のあるinitスクリプトの構造を提供することを目的としたOpenRCご覧ください。


2
「initスクリプトタイプを見る」とはどういう意味ですか?多くの場合、異なる初期化システムは、/etc/initsystemdがそれらを配置するように、スクリプト/ファイルをどこかに配置します/etc/systemd。私のスクリプトにこれらを理解させるには、少し時間がかかります。ああ、ポータブルシェルプログラミングのリンクBTWに感謝します。
beatgammit

1
いくつかのinit実装を調整して、異なるinitスクリプトのタイプと場所(/etc/rc.d/またはなど/etc/init.d/)を使用できるようにすることを意図しました。また、インストール時にプログラム適切に調整して、特定のシステムで使用される構造を利用する必要があります。
rozcietrzewiacz

2
だから、あなたはプログラムでinitシステムを検出する信頼できる方法がないと言っていますか?ユーザーにパラメーターを渡すことは確かに安全ですが、ユーザーが何も渡さない場合、推測する最良の方法は何でしょうか?
beatgammit

あなたのプログラムにとって最良の方法が何であるかはわかりません-それはすべて、プログラムが最終的に実行されるシステムに依存します。私はあまり多くのディストリビューションを使用していませんが、あなたを助けるために私の意見を共有しようとしていました。これはあなたがやろうとしているスクリプティングの難しい部分であり、私はあなたにフィールドについてのいくつかの見解を与えようとしました。
rozcietrzewiacz

よろしくお願いします。あなたは間違いなく私を正しい方向に向けてくれました。
beatgammit

58

私は自分でこの問題に踏み込んで、いくつかのテストを行うことにしました。ディストリビューションごとに個別にパッケージ化する必要があるという答えには完全に同意しますが、それを妨げる実用的な問題がある場合もあります(特に人的資源)。

そのため、「自動検出」したい人のために、限られた一連のディストリビューションで私が見つけたものを以下に示します(以下で詳しく説明します)。

  • 以下からupstartを伝えることができます。

    [[ `/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インスタンス(us-east AMI idを含む):

  • ArchLinux:systemdを使用(2012.10.06以降)
  • CentOS6.4 ami-52009e3b:upstartの使用
  • CentOS7 ami-96a818fe:systemdを使用
  • Debian 6 ami-80e915e9:sysv-initを使用
  • Debian 7.5 ami-2c886c44:sysv-initの使用
  • Debian 7.6 GCE container-vm:sysv-initを使用
  • RHEL 6.5 ami-8d756fe4:upstartの使用
  • SLES 11 ami-e8084981:sysv-initの使用
  • Ubuntu 10.04 ami-6b350a02:upstartを使用する
  • Ubuntu 12.04 ami-b08b6cd8:upstartを使用する
  • Ubuntu 14.04 ami-a427efcc:upstartを使用する
  • Ubuntu 14.10以下:systemdを使用する
  • AWS Linux 2014.3.2 ami-7c807d14:upstartの使用
  • Fedora 19 ami-f525389c:systemdを使用する
  • Fedora 20 AMI-21362B48:systemdを使用する

明確にするために、これが絶対確実だと主張しているわけではありません!、そうではありません。また、便宜上、どこでも利用できないbash正規表現一致を使用しています。上記はこれで十分です。ただし、失敗したディストリビューションを見つけた場合はお知らせください。問題を再現するEC2 AMIがある場合は修正を試みます...


5
systemdのドキュメント(sd_booted(3))によると、systemd をチェックする正しい方法は、ディレクトリ/run/systemd/systemが存在するかどうかをチェックすることです。
ロビービーサック

1
この検出launchdに追加します、macOSのinitシステム:[[ $(ps 1) =~ 'launchd' ]] && echo yes || echo noMacBookPro、macOS Sierraバージョン10.12でテスト済み
トニー

私はまた、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のさまざまなバージョンを検出できるいくつかのコマンドからの出力を見ると、次のように作成できます。systemdupstart

起業家

$ 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。Upstartを使用したUbuntuでは、まだ/sbin/initです。

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

注:ただし、これは少し注意して使用してください。特定のディストリビューションで使用されている特定のinitシステムがPID#1として持っている必要があると言っているものは何もありませんsystemd

ジェネリック

$ (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システムを指している場合があります。

ファイルシステム

あなたが尋問した場合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/initsysvinitシステム上にあります。

sysvinit

$ type init
init is /sbin/init

これも:

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

結論

したがって、それを行う方法はありませんが、使用している初期化システムをかなり高い信頼性で特定する一連のチェックを作成できます。


方法:pgrep systemd >/dev/null && echo init system: systemd
マルコ14

ありがとう、これはまさに私が探していたものです:initシステムを決定しようとするためのいくつかのステップ。
user369450 14

1
/usr/lib/systemd/systemdsystemdが使用されている場合、PID#1は必ずしもそうではなく、誤った仮定です。たとえば、私のシステムでは、PID#1は/sbin/init(私はsystemdを使用しています)。配布に依存します。
マルコ14

kubuntu 15.04のインストールでは、systemdとsysvinitの両方があるようです。知ってはいけない理由やそれが何を意味するのか、ただ言って... pgrep systemd >/dev/null && echo init system: systemd -> init system: systemdtype 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で使用される文字列はわずかに変更できますが、次のOSでテストすると、常に1行になります。

  • RHEL 6.4 [アップスタート]
  • RHEL ES 4(Nahant Update 7)[SYSVINIT]
  • Ubuntu 16.04.1 LTS [システム化]
  • Ubuntu 14.04.2 LTS [アップスタート]
  • 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へようこそ!
オリビエデュラック

OpenRCがインストールされたGentooデフォルトのdockerイメージでこれを試したところ、SYSVINITが返されました。wiki.gentoo.org/wiki/Comparison_of_init_systemsによると、GentooのデフォルトはOpenRCですが、OpenRCはsysvinitを使用しているようです。OpenRCコマンドを実行しようとすると、「openrcが起動しなかったシステムでOpenRCサービスを実行しようとしています」というメッセージが表示されます。sysvinitを使用して、sysvinit固有とOpenRCを区別する方法はありますか?
チューダー

9

時にはそれを使用するのと同じくらい簡単ls です:

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

/sbin/initシンボリックリンクでない場合は、他の回答の次の提案をさらに確認する必要があります。


3
  1. これがディストリビューション固有のパッケージの目的です。ソフトウェアを適切にインストールすることは、単にinitシステムを検出するだけではありません。多くのディストリビューションはSysVinitを使用しますが、すべてのディストリビューションが同じ方法で初期化スクリプトを作成するわけではありません。これを解決する適切な方法は、すべての異なるバリアントを含めてから、rpmディストリビューションのディストリビューション固有の依存名、aptベースのシステムのdebファイルなどを含むスペックファイルを使用してバンドルすることです。依存関係、スクリプト、initスクリプトなどを含む書き込みが可能です。ここで車輪を再発明しないでください。

  2. いいえ。1に戻ります。bashが必要な場合は、依存関係にする必要があります。このチェックは、configureスクリプトの一部として指定できますが、パッケージの説明にも含まれている必要があります。

編集:--with upstartやなどの構成スクリプトでフラグを使用します --without sysvinit。適切なデフォルトを選択すると、他のディストリビューション用にソフトウェアをパッケージ化するスクリプトは、他のオプションでこれを実行することを選択できます。


Hmph、だから「すべてを支配する1つのスクリプト」ソリューションを持てないように見えます。autoconfなどを使用してクロスプラットフォームのものを処理するプログラムを見てきましたが、アプリケーションに適したツールではないようです。各プラットフォームのバージョンを維持することが本当に唯一の信頼できるソリューションですか?
beatgammit

それらすべてを支配する1つのインストールスクリプトはBadIdeaです。動作するよりも多くの場所で失敗することになります。Autoconfは、それができる限り優れています。ソフトウェアの最後をできるだけ汎用的に保ち、パッケージに別の初期化スクリプトを含めるように努めてください。いくつかの主要なディストリビューションのパッケージ仕様をセットアップします。お使いのソフトウェアが優れている場合、他のシステム用にパッケージ化するのを手伝ってもらうことができます。
カレブ

@tjameson:最も重要なことを忘れてしまったことに気付きました。この種のことは、通常、configureスクリプトに渡されるスイッチを使用して行われます。各ディストリビューションのビルド/パッケージルーチンは異なるスイッチを呼び出すことができ、configure / makeは渡されたスイッチを知るだけでよく、すべての可能なソフトウェア構成を検出する必要はありません。
カレブ

@カレブ-ええ、私はすでにそこにそのロジックを持っていますが、良いキャッチ。私は、正常なデフォルトよりもインテリジェントな推測を使用するために、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のもう1つの方法profile-config showは、を使用することです。これは、使用されているデフォルトプロファイルを表示します。/ systemdで終わる2つを除くすべてのプロファイルは、OpenRC initを使用します。これらはデフォルトの代表に過ぎず、ユーザーがそのデフォルトを上書きするための措置を講じた可能性があり、実際に使用されているinitマネージャーを示していない可能性があります。


バカな質問ですが、pid 1を確認するにはどうすればよいですか?
ファヒムミタ14

使用p(と同一のオプション-pとを--pidPIDで選択するように)。上記のスニペットは、実際にはの出力ですps u --pid 1
ホセM.ベニテス

2

debianでは、/ sbin / initはデフォルトのinitへのシンボリックリンクです。

ls -l /sbin/init

あなたが探している情報を提供します。

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

1
そうではありません。Upstartを使用したUbuntu 14.04では、シンボリックリンクではありません。
ムル14

別のinitシステムをインストールして、もう一度確認してください。
rmorelli74 14

またinit、Ubuntu 14.04にインストールできる他のものはどれですか?
ムル14

...なぜsysvやsystemdではないのですか?
rmorelli74 14

1
投票したくありません。適用するDebianのバージョンを指定してください。(そして、おそらく「Debianベース」を「Debian」のみに言い換えて、正しいものになるようにしてください。)
muru 14

2

PID 1を使用してプロセスを単純に調べると、次のことがわかります。

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

言及されたすべてのOSeSにprocファイルシステムがあるわけではありません...
Toby Speight

2

ファイル記述子を調べることも役立ちます。そして、それは実際にinitを実行しているからです(Debian stretchは現在、より多くの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は通常symlinksを使用するため、busyboxをチェックするより安全な方法は次のとおりです。

$ 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ます。
ペビック

2

Debian(wheezy)/ Ubuntu(14.10。)以外の他のシステムについては知りませんが、このような問題は単純な古いfileコマンドでテストします。

file /sbin/init

これを与える:

/sbin/init: symbolic link to 'upstart'

systemd(例えばsid)を備えたDebianシステムはこれを示します:

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

どのシステムでテストしましたか?Debian / Ubuntuのようなものはなく、これはDebianでは機能しません。Ubuntuで試しましたか?
テルドン

この混乱のためにすみません、私はDebian(wheezy)/ Ubuntu(14.10。)を意味します。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 ここでSYSVを使用することを意味します。ubuntuの出力は私の答えに示されています。
zzeroo

まさにそのため、あなたのソリューションはたまたまupstartとUbuntuを使用している場合にのみ機能するようです。
テルドン

@terdon:systemdを実行しているシステム(RHEL、Fedora)では、「... symbolic link to ... systemd」を返します。upstartを実行しているシステム(Ubuntu)では、「symbolic link to upstart」を返します。SysV initを実行しているシステム(RHEL、Ubuntu、Debian)では、「実行可能」を返します。これは包括的な調査ではありませんが、この方法は100%確実なわけではありませんが、「新興企業とUbuntuのみ」ではなく、「少なくとも主要なディストリビューションで動作する」に明らかに近い方法です。
psmears 14年

1
一部のsystemdシステムでも動作する場合は@psmearsです。これは確かに優れています(ただし、この回答には記載されていません)。sysvinitを実行しているDebianと3つのUbuntu(10.04、12.04、14.04、すべて実行中)でテストし、file /sbin/initすべてのシステムで「実行可能」を 返しました。CentOS 5.8、SLES 10、Ubuntu 8.04、基本的に私が手に入れることができるすべての単一システムでも同じを返します。だから、私が知る限り、それは新興企業やUbuntuでも機能しません。
テルドン

2

私もこれと同じ問題を抱えており、いくつかのRedHat / CentOS / Debian / Ubuntu / Mintマシンで多くのテストを行いました。これが私が最終的に良い結果をもたらしたものです。

  1. PID 1の実行可能ファイルの名前を見つけます。

    ps -p 1

    systemdまたはUpstartの場合、問題は解決しました。「init」の場合は、シンボリックリンクまたは先行名以外の何かである可能性があります。どうぞ。

  2. 実行可能ファイルの実際のパスを見つけます(rootとしてのみ機能します):

    ls -l `which init`

    initUpstartまたはsystemdへのシンボリックリンクの場合、問題は解決しました。それ以外の場合、SysV initを持っていることはほぼ確実です。ただし、実行可能ファイルの名前が間違っている可能性があります。どうぞ。

  3. 実行可能ファイルを提供するパッケージを見つけます。残念ながら、これはディストリビューションに依存しています。

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

次に、それをスクリプト化する場合(最も面白い部分、私見)、これらは私のワンライナーです(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
指定されたすべてのオペレーティングシステムがdpkgまたはrpmを持っているわけではありません(この問題はあなたの答えだけではありません、BTW)。
トビー・スペイト

@ toby-speightはい、確かです。注:制限を明確にするために、回答でそのように述べました。
エマーソンプラド

ステップ3についてはinit --version、情報を取得するために実行できます。
jarno

1

これは、一部の初期化システムでは非常に簡単です。systemdの場合:

test -d /run/systemd/system

新興企業向け:

initctl --version | grep -q upstart

その他については、ディストリビューション(OS Xで起動、Debianでsysvinit、GentooでOpenRC)に基づいて想定できます。


「仮定のディストリビューションに基づいて」...サポートされている少なくとも三つの異なるのINITのDebian、動作しません
トビースパイツ

1

検出を行うbashスクリプトを次に示します。現時点ではupstartと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(適切に構成されている場合)と他の1つまたは2つに結び付けていると思います-それは確かに普遍的とはほど遠いです。
トビーSpeight

1

systemdと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

これは多数の既存の回答と比較して、この回答では新しい情報や異なる情報が提供されないためです。
jayhendren

@jayhendrenこのスニペットは他のどこにもありません。それ自体は完全ではなく、おそらく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マシンにしかアクセスできないため、Upstartまたは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.