サービスがスクリプトで実行されているかどうかをテストする「適切な」方法


96

私の問題:

私はbashスクリプトを書いていますが、その中で特定のサービスが実行されているかどうかを確認したいと思います。

私はこれを手動で行う方法を知っています$ service [service_name] status

しかし、(特にsystemdへの移行以来)解析するのが少し面倒なテキスト全体を印刷します。単純な出力または確認できる戻り値を持つスクリプト用に作成されたコマンドがあると想定しました。

しかし、グーグルで動き回っても「ああ、ただps aux | grep -v grep | grep [service_name]」という結果しか得られません。それはベストプラクティスとは言えませんね。そのコマンドの別のインスタンスが実行されていて、SysV initスクリプトによって開始されたものではない場合はどうなりますか?

それとも、黙って小さなpgrepで手を汚すべきですか?

回答:


140

systemctlこれにはis-activeサブコマンドがあります:

systemctl is-active --quiet service

serviceアクティブな場合はステータスゼロで終了し、そうでない場合はゼロ以外で終了します。

systemctl is-active --quiet service && echo Service is running

省略--quietすると、現在のステータスも標準出力に出力されます。

don_crisstiによって指摘されているように、一部のユニットは、サービスを提供するために何も実行されていない場合でもアクティブになります。「RemainAfterExit」とマークされたユニットは、 (たとえば、システムの一部を構成します)。ただし、デーモンを含むユニットは、デーモンがまだ実行中の場合にのみアクティブになります。


ワンショットサービスに注意してください。それらは唯一でありinactive、またはactivating両方systemctl statussystemctl is-active3と出口(のようにsystemd-241)回避方法:systemctl show service | grep -qx ActiveStatus=activating
アロイスMahdal

@Aloisワンショットサービスをアクティブにすることを検討したい場合、どのようなシナリオに遭遇したのでしょうか。例はありますか?
スティーブンキット

確かに、@ StephenKitt。このツールfooは、再起動を伴うシステムに対して何かを実行し、たとえば、foo_cleanup次回のブート時にワンショットサービスを使用してクリーンアップします。私はこれをテストしています(私のスクリプトもサービスとしてスケジュールされています)、後でエラーを収集したいのですが、その後いつですか(vsauce music)?基準の1つは、foo_cleanup終了したことです(「アクティブ化の停止」)。
アロイス・マーダル

「失敗」もオプションであり、開始されていないサービスに基づいてアクションを実行する必要がある場合に役立ちます。
フィルヒーリー

33

systemctlスクリプトに適したモードがあります。でshowなくを使用し、必要な出力のみを取得statusするために-p/ --propertiesおよび--valueオプションを追加します。

次に例を示します(Ubuntu 17.04システムから)。

$ systemctl show -p SubState --value NetworkManager
running

実行中(またはそれ以外)はSubStateです。サービスがアクティブかどうかを知りたい場合は、プロパティを使用しますActiveState

$ systemctl show -p ActiveState --value x11-common
inactive
$ systemctl show -p SubState --value x11-common
dead

からのメモman

show [PATTERN...|JOB...]
           Show properties of one or more units, jobs, or the manager
           itself. If no argument is specified, properties of the
           manager will be shown. If a unit name is specified, properties
           of the unit are shown, and if a job ID is specified,
           properties of the job are shown. By default, empty properties
           are suppressed. Use --all to show those too. To select specific
           properties to show, use --property=. This command is intended
           to be used whenever computer-parsable output is required. Use
           status if you are looking for formatted human-readable output.

-p, --property=
           When showing unit/job/manager properties with the show command,
           limit display to properties specified in the argument. The
           argument should be a comma-separated list of property names,
           such as "MainPID". Unless specified, all known properties are
           shown. If specified more than once, all properties with the
           specified names are shown. Shell completion is implemented for
           property names.

--value
           When printing properties with show, only print the value, and
           skip the property name and "=".

2
洗練された答えのために+1。--versionsystemctlでオプションを受け入れるディストリビューションを親切に指定してください。
SKヴェンカト

11

Zannaの答えを補完するものとして、の--valueオプションがsystemdのバージョン230でsystemctl show導入されました。そのため、debian jessieのような特定のディストリビューションでは利用できない場合があります。

この場合、sedを使用してオプションをエミュレートできます。

$ systemctl show -p ActiveState sshd | sed 's/ActiveState=//g'
active
$ systemctl show -p SubState sshd | sed 's/SubState=//g'  
running

1
+1は、機能しない--valueイントロバージョンとディストリビューションを指摘しました。
SKベンカット

3

これは、コマンドラインの実行またはスクリプトを作成する場合に便利です。

@StephenKittからコピー

これは、サービスがダウンしているかどうかを確認し、サービスの再起動を実行します

systemctl is-active --quiet <service name> || <service name> restart

||systemctlからの戻り値は、著者によって説明したように、それはアクティブでなければゼロ以外の意味である場合がチェックされます。


また、「is-failed」を使用して、再起動が必要かどうかをテストすることもできます。失敗したサービスを再起動する方が少し直感的です。
フィルヒーリー

はい、しかし私のために..私は自分自身を練習し、そうでないときはすべてが実行されていると仮定したかった。それで、私は物事がそれで他のものを確かめることに行くことができます。単に、実行していないかどうかだけを確認したい場合は、「is-failed」が正しい選択です。:)
アスタリスク

3


私はパーティーに遅すぎますが、systemctl is-active をこれ&&と一緒に使用し、||これにスクリプトで常に使用することはありません。以下はTomcatで使用したものですが、複数のサービスをチェックする必要があるが、ここでは範囲外の場合、引数を取るメソッドで使用し、引数としてサービス名を渡すことができます。

STATUS=`systemctl is-active tomcat.service`
  if [[ ${STATUS} == 'active' ]]; then
    echo "Execute your tasks ....."
  else 
    echo " Service not running.... so exiting "  
    exit 1  
  fi

これが私が利用した方法です。

そして、シンプルで簡単なもののために、ここで説明されている他の人に従ってください:

systemctl -q is-active tomcat.service  && echo "Tomcat Runnung" || echo "Service is not running at all "

それは単純に比べてどうif systemctl is-active --quiet tomcat.serviceですか?また、[[標準シェルではありません。
トビースパイト

@TobySpeight私の投稿で述べたように、私の投稿をもう少し読む必要があります。シェルの標準的な使用法であるとは言いませんでした。単一のブラケットにすると、それはその後になりますが、ここでは範囲外です。さらに私は、以下の使用してそれを行うための簡単な単一ラインの使用に言及&&して||
サガーネイル

2

Oxmelの答えのようにsedコマンドを使用する代わりに、cut -d'=' -f 2クエリされるすべての種類のプロパティに使用するだけで十分です。

例えば:

$ systemctl show -p ActiveState sshd | cut -d'=' -f2
active
$ systemctl show -p SubState sshd | cut -d'=' -f2
running

それは素晴らしいことですが、これらのコマンドが何をするのかについて説明する必要があります。
フィルヒーリー

-1

この素晴らしい小さなスクリプトを見つけました:

#!/bin/bash
service=replace_me_with_a_valid_service

if (( $(ps -ef | grep -v grep | grep $service | wc -l) > 0 ))
then
  echo "$service is running!!!"
else
  /etc/init.d/$service start
fi

ソース


すべてのサービスに同じ名前の実行可能ファイルがあるわけではなく、ユーザーが誤って一致するコマンドを実行している可能性があります-これは災害のレシピです。
トビースパイト
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.