シェルを使用した初期化システムの検出

シェルを使用した初期化システムの検出

これはおそらくオペレーティングシステムの検出に関連しているかもしれませんが、特に現在システムで使用されているinitシステムが必要です。

Fedora 15とUbuntuはsystemdを使用し、UbuntuはUpstart(15.04までのデフォルト)を使用し、他のバージョンはSystem Vバリアントを使用します。

私はクロスプラットフォームデーモンでアプリケーションを書いています。初期化スクリプトは、構成中に渡されたパラメーターに基づいて動的に生成されます。

私が望むのは、彼らが使用している特定の初期化システム用のスクリプトを生成することだけです。このように、インストールスクリプトは引数なしでルートとして合理的に実行でき、デーモンは自動的に「インストール」されます。

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

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

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

ある程度関連があり、ほとんどの* nixをサポートするためにbashを使用できますか?それとも配布/OSに依存していますか?

ターゲットプラットフォーム:

  • アップルシステム
  • Linux(すべてのディストリビューション)
  • BSD(全バージョン)
  • Solaris、Minix、その他 *nix

答え1

私はこの問題に直接直面し、いくつかのテストを行うことにしました。流通ごとに別々の梱包が必要だという回答には全く同意しますが、時には現実的な問題(特に人材)がある場合があります。

だから、「自動検出」をしたい人のためにこれが私が見つけたものです。限られた配布セットについて(詳細は以下から):

  • 次のことで、スタートアップを見つけることができます。

    [[ `/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コンテナ仮想マシン: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があれば修正するよう努力いたします。

答え2

2番目の質問に対する答えは次のとおりです。いいえあなたは少し見なければなりません。ポータブルシェルプログラミングリソース

最初の部分については - まず注意してください。私が言うこと複数のテストを実行して保証します。- 実際に人がいるからもちろんたとえば、systemdがインストールされているため、実際にはデフォルトですinit。また、さまざまなinitプログラムの一部のインストールが自動的にシンボリックリンクハードリンクを生成したり、さらに基本プログラムの名前が変更されたバージョンを生成することができるので、見ることが誤解を招く可能性が/proc/1/commあります。/sbin/init

おそらく最も有用なのは、initスクリプトの種類を見てみることです。これは、実行している項目に関係なく実際に作成したいものです。

ところで、あなたも確認できますオープンRCその目的は、LinuxおよびBSDシステムと互換性のあるinitスクリプト構造を提供することです。

答え3

手動

&のさまざまなバージョンを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

システム

$ 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のプロセス名は、どの初期化システムが使用されているかを理解するのに役立ちます。 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

メモ:ただし、使用するときは注意してください。特定のディストリビューションで特定の初期化システムが使用されていることを示す決まったものはありません。持つsystemdPID#1に。

一般的な

$ (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ファイルからいくつかの情報を取得できます。単に--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.

システム

$ type init
init is /usr/sbin/init

メモ:それが標準位置にないという事実は、init少し暗黙的/提案的です。常に/sbin/initsysvinitシステムにあります。

システムベネット

$ type init
init is /sbin/init

これ:

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

結論として

したがって、これを行う方法はないようですが、どの初期化システムを使用しているかを非常に高い信頼性で正確に見つける一連のテストを開発できます。

答え4

時には以下を使うのと同じくらい簡単ですls 。

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

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

関連情報