ネットワークの開始後にスクリプトを実行しますか?


102

私はsystemdが比較的新しく、そのアーキテクチャを学んでいます。

現在、カスタムシェルスクリプトを実行する方法を見つけようとしています。このスクリプトは、ネットワーク層の起動に実行する必要があります。

systemdとnetctlを使用してArchを実行しています。

テストするために、単に実行する単純なスクリプトを作成しましたip addr list > /tmp/ip.txt。このスクリプト用に次のサービスファイルを作成しました。

(/etc/systemd/system/test.service)
[Unit]
Description=test service

[Service]
ExecStart=/root/test.script

[Install]
WantedBy=multi-user.target

次に、スクリプトを有効にしました。

systemctl enable test

再起動すると、スクリプトは実際に実行されますが、ネットワークが開始される前に実行されます。つまり、出力にip.txtは、プライマリインターフェイスに割り当てられたIPv4アドレスは表示されません。ログインするまでに、IPv4アドレスは実際に割り当てられており、ネットワークは稼働しています。

WantedByパラメーターを変更することで、スクリプトを実行するポイントを変更できると思いますが、その方法はわかりません。

誰かが私を正しい方向に向けることができますか?

回答:


126

systemdネットワーク構成の依存関係

systemdのユニットの順序に影響を与えることは非常に簡単です。一方、完成したユニットが保証するものに注意する必要があります。

サービスを構成する

現在のシステムでは、注文後network.targetにネットワークサービスが開始されていることを保証するだけで、実際の構成が存在することは保証されません。あなたはnetwork-online.targetそれを達成するために後で注文し、それを引っ張る必要があります。

[Unit]
Wants=network-online.target
After=network-online.target

古いシステムとの互換性のために、network.targetの後にも注文する必要があるかもしれません。

[Unit]
Wants=network-online.target
After=network.target network-online.target

これは、サービスのユニットファイルとsystemdの場合です。

ソフトウェアの現在のバージョンでの実装

次に、それがnetwork-online.target期待どおりに動作すること(または少なくともを使用できることnetwork.target)を確認する必要があります。

NetworkManagerの現在のバージョンは、サービスNetworkManager-wait-online.serviceによってnetwork-online.target、したがってサービスによって取得されるものを提供します。この特別なサービスにより、開始するように構成されたすべての接続が自動的に成功、失敗、またはタイムアウトするまで、サービスが待機します。

systemd-networkdの現在のバージョンは、すべてのデバイスが要求どおりに構成されるまでサービスをブロックします。現在は、ブート時に適用される構成(より具体的には `systemd-networkd.serviceの起動時)のみをサポートするという点で簡単です。

完全を期すために/etc/init.d/network、Fedora のサービスは、systemdの現在のバージョンで解釈されるnetwork.targetようにnetwork-online.target、サービスをブロックし、間接的にブロックします。これは、スクリプトベースの実装の例です。

デーモンベースまたはスクリプトベースの実装が上記のネットワーク管理サービスの1つとして動作する場合、ネットワーク構成が正常に完了するか、正当な理由で失敗するか、妥当な時間後にタイムアウトするまで、サービスの開始を遅らせます完了するフレーム。

netctlが同じように機能するかどうか、またこの情報がこの回答に追加される価値があるかどうかを確認することができます。

古いバージョンのソフトウェアでの実装

systemdの十分に古いバージョンでは、これがうまく機能しないのではないでしょうか。しかし、少なくともnetwork-online.target存在することと、それが後に注文されることを確認できますnetwork.target

以前は、NetworkManagerは少なくとも1つの接続が適用されることのみを保証していました。そして、それが機能するためには、NetworkManager-wait-online.service明示的に有効にする必要があります。これはFedoraで長い間修正されてきましたが、最近になってアップストリームに適用されました。

systemctl enable NetworkManager-wait-online.service

network.targetおよびnetwork-online.targetの実装に関する注意

ソフトウェアを他の特定のサービスに依存させNetworkManager.serviceたりNetworkManager-wait-online.service、他の特定のサービスに依存させたりする必要はありません。代わりに、すべてのネットワーク管理サービスは、前network.targetにオプションで自分自身を注文する必要がありますnetwork-online.target

単純なスクリプトベースのネットワーク管理サービスは、終了する前にネットワーク構成を終了し、前にnetwork.target、したがって間接的に前に自身を順序付けする必要がありnetwork-online.targetます。

[Unit]
Before=network.target

[Service]
Type=oneshot
ExecStart=...
RemainAfterExit=yes

デーモンベースのネットワーク管理サービスは、network.targetあまり有用ではありませんが、事前に注文する必要があります。

[Unit]
Before=network.target

[Service]
Type=simple
ExecStart=...

デーモンが終了するのを待つサービスは、特定のサービスの後、前に自分自身を注文する必要がありますnetwork-online.targetRequisiteそれぞれのネットワーク管理サービスが使用されていない場合にすぐに失敗するように、デーモンサービスで使用する必要があります。

[Unit]
Requisite=...
After=...
Before=network-online.target

[Service]
Type=oneshot
ExecStart=...
RemainAfterExit=yes

パッケージは、設定されたネットワークを待機するサービスによって取得されるように、wantsディレクトリ内の待機中のサービスへのシンボリックリンクをインストールするnetwork-online.target必要があります。

ln -s /usr/lib/systemd/system/... /usr/lib/systemd/system/network-online.target.wants/

関連資料

最終ノート

あなたが質問したときにあなたの質問に答えるだけでなく、アップストリームおよびLinuxディストリビューションの状況を改善することに貢献したことを願っています。 。


「自動的に開始されるように構成されたすべての接続が成功するまで待機する」という自動接続オプションを意味しますか?no-auto-default = *を設定しても、接続の1つにautoconnect = yesがある場合、これを活用できますか?最後の質問-nm-onlineの--wait-for-startupオプションがわかりません。マニュアルページはあまり役に立ちません。この記事をお寄せいただきありがとうございます。
lzap

私の知る限り、nm-onlineは気にしませんno-auto-default、だけautoです。具体的な質問はありますか?私の意見では、nm-onlineのマンページには-s、すべての自動接続が試行される、つまり接続または失敗するのを待つと明記されています。
パベルシメルダ

このがらくたを1時間いじった後、私は解決策を見つけました:apt-get install sysv-init。:-) systemdが追加する複雑さは、いくつかのシェルスクリプトの代替として気が遠くなるほどで​​す。
誰か

@Someoneこの場合、initscriptは答えではないのではないかと心配しています。NetworkManagerまたは他の動的構成ツールを使用している場合、initscriptsは、完全に構成されたネットワークの後には順序付けできません。/etc/init.d/networkまたはを使用して、限られた動的構成を取得できますが、それは普遍的には機能しません。
パベルシメルダ

@PavelŠimerdaInitはシリアルで実行され、適切なinitスクリプトは、後続のスクリプトが依存する必要のある処理を完了するまで戻りません。ネットワーキングの場合、適用可能なすべてのアダプターを準備しておく必要があります。幸運なタイミングでない限り、NMはそのコンテキスト内で適切に動作します。もちろん、実際の問題は、NMが既存の単純で試行され、テストされた構造を構築する代わりに、ネットワーク処理を再発明することです。デスクトップの人々は、複雑さの危険性の概念を持っていないようです。;-)
誰か

9

あなたは使用することができますAfter[Unit]あなたのサービスが開始される前に開始されるサービスを定義するセクション。たとえば、NetworkManagerを使用している場合、NetworkManagerの開始後にサービスを開始できます。

[Unit]
Description=test service
After=NetworkManager.service

BindsToサービスは一時的なイベントであり、永続的なサービスではないため、ここではあまり適切ではありません(ExecStopネットワークがダウンしたときに起動する機能も含まれていない限り)。
goldilocks 14

削除BindsTo
フープ14

BindsToただし、NetworkManagerがRequires実行する場合にのみサービスを実行する場合など、置換するものを追加できます。 After実際にそれを行うわけではありません。NMが実行されている場合は、後で実行するだけです。NMが実行されない場合、サービスは任意のポイントで実行されます。
goldilocks 14

4
After = network.targetは、より汎用的であるため、After = NetworkManager.serviceよりも優れています。
パベルシメルダ14

7
指定するAfter=fooと、ユニットがまだ開始されていない場合はfooユニットが開始され両方が同時に開始された場合にユニットの順序付け方法のみがsystemdに通知されます。または両方After=fooを使用すると、開始されていない場合にプルインし、systemdにユニットを正しく順序付けさせる効果があります。Wants=fooRequires=foofoo
エミルルンドバーグ14

8

サービスがサーバーを提供し、誰かが接続するのを受動的に待つことができる場合は、これを使用します:

[Unit]
After=network.target

サービスはワイルドカードインターフェイスにバインドする必要があります。ソケットアクティベーションを使用する場合(推奨)、またはローカルのみの場合は、ネットワークターゲットを完全に無視できます。

サービスがクライアントとして機能する場合、またはピアツーピアである場合、これはより適切です。

[Unit]
After=network-online.target
Requires=network-online.target

systemd 213の前に、network-online.targetには前述の回避策が必要です(ネットワークが起動するのを待つサービスを手動で有効にする必要があります)。systemd 213現在、これはデフォルトで行われています。systemd-networkd-wait-online少なくとも1つのアドレス(ルーティング可能またはリンクローカル)が非ループバックインターフェイスに設定されるのを待ちます。

systemd-networkd、NetworkManager、または同等の設定は、独立したタスクです。DHCP(IPv4の場合)およびNDP(IPv6の場合)はそのままで動作する傾向がありますが、「ネットワークが稼働している」という正確な定義がトリガーとなるようにそれらを構成する必要がありますnetwork-online.target

ドキュメンテーション:


既存の(うまくいけば)うまく構成された回答に対する小さな改善だけでなく、なぜ新しい回答が必要なのか興味があります。
パベルシメルダ14

最初の2つのドキュメントリンクは現在無効です。
ピーターハンセン

Wantの代わりにRequiresを使用するのはなぜですか?
カールモリソン

4

WantedByパラメータをいじることで、スクリプトを実行するポイントを変更できると思います

それはあなたが望むものとは逆の効果を持つでしょう。からman systemd.unit

WantedBy =、RequiredBy =

[...]シンボリックリンクは、このユニットがsystemctl enableによってインストールされるときに、リストされた各ユニットの.wants /または.requires /ディレクトリに作成されます。これには、Wants =またはRequires =タイプの依存関係がリストされたユニットから現在のユニットに追加されるという効果があります。

これに基づいて、適切なユニットオプションが「Wants」または「Requires」であることがわかります。それらの説明に基づいて、「Requires」はおそらく正しいです。「After」を追加して、ネットワーキングサービスを実行するだけでなく、このユニットの前に実行するようにします。

ユニットのオプションのいずれも、私の知る限り、開始役得が完了、またはそれだけであること、(ネットワーキングはおそらくデーモンサービスである)特定のポイントに達していなければならないという規定を含めることはできません開始する最初の。これを念頭に置いて、Type=forking最初にDHCPリースがあることを確認するために、スクリプトを作成して健全な遅延(たとえば30秒)、または遅延を含む何らかの成功時終了ループをスローすることができます。


1
WantedByもRequiredByも順序に影響しません。
パベルシメルダ14

1
@PavelŠimerda:ここで誰も彼らがそう主張したわけではありません。「ネットワークサービスが実行されるだけでなく、このユニットよりも前に実行されるようにするため」Afterと一緒に明示的に言及したのは順序ですRequires
goldilocks 14

1
はい、After一緒にWantsまたはRequiresそのように動作します。一方、明示的な遅延は、特にsystemdのドキュメントで指定されたネットワークが設定されるまで明示的に待機する方法がある場合、依存関係ベースのツールでは悪い習慣です。そのため、私は下票を主張しなければなりません。
パベルシメルダ14

3

セクションで使用Afterして[Unit]、独自のサービスの前に何を開始するかを指定します。(これまでの答えの多くは正しいです。)

ネットワークの起動後にサービスを開始するには、NetworkManager、Archのconf.d / netctlシステム、またはsystemdが認識している他のサービスを使用するかどうかに関係なく、ネットワークターゲットを使用します。

[Unit]
#.....
After=network.target

簡単に見てみると、ネットワーク接続に依存するシステム上の他のすべてサービスにこのディレクティブが含まれていることが確認できます。

また、systemdを使用するすべてのディストリビューションに移植可能です。ユニットファイルは、Arch、Fedora、RHEL 7、Debianの将来のバージョンで同じになります...


Archのスクリプトや独自のスクリプトなど、ネットワーク接続を開始するサービスは、独自のユニットファイルで指定する必要があります。

[Unit]
Wants=network.target
Before=network.target

Wants他のパッケージに副作用があるため、私はこの部品が完全に好きではありません。私の答えを見てください。
パベルシメルダ14

ここで、Wantson network.targetが良いアイデアであることに気付きました。
パベルシメルダ14

あなたは本当にnetwork-online.targetを使いたいのです。ref
エドワードトーバルズ

1

この記事にポイントを追加したかった。現在(2015年夏)RHEL7 / CentOS 7では、IPv6ネットワークが起動する前にnetwork-online.targetが誤って設定されているため、

Wants=network-online.target
After=network-online.target

IPv6アドレスに明示的にバインドするサービス定義では、おそらくIPv6が起動して実行される前に開始され、それらが失敗します。


これは、カーネルベースのIPv6自動構成の場合にのみ当てはまると思いますが、とにかく欠陥があります。IPv6の後に適切に注文したい場合は、間違いなくNetworkManagerを使用する必要があり/etc/init.d/networkます。NMを使用しても同じ問題が発生する場合は、機能リクエストを提出することをお勧めします。RHEL / CentOSで確認したことはありませんが、興味があれば詳細をお伝えします。
パベルシメルダ16

0
[Unit]
After=systemd-networkd.service

私のために働く。


いくつかの特別なケースで機能するかどうかはわかりませんが、いくつかの理由で間違っています。その1つnetworkdは、独自の/ wait-online /サービスを提供することです。引き込んで注文network-online.targetすることは、それをサポートするサービスを利用する正しい方法です。
パベルシメルダ16
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.