奇妙なこと:私はspringboot fat archive Webサーバーを起動するサービスを作成しました。提供する:
#!/bin/bash
[Unit]
Description=JalouWeb
[Service]
Type=simple
WorkingDirectory=/opt/jaloucontrol
ExecStart=/bin/bash jalouweb.sh
TimeoutStartSec=0
RestartSec=60
Restart=always
SyslogIdentifier=jalouweb
[Install]
WantedBy=multi-user.target
jalouweb.sh:
#! /bin/sh
#
java -Duser.timezone=Europe/Berlin -Dfile.encoding=UTF-8 -jar jcweb-0.0.1-SNAPSHOT.jar
jalouweb.shをユーザーとして起動するだけです。 sudo -iを実行し、jalouweb.shをrootで始めます。ユーザーとルートの両方が正常にjava -versionを呼び出すことができます。
ただし、systemctlを介してサービスを開始すると、次のメッセージが表示されます。
... jalouweb.sh: Zeile 3: java: Kommando nicht gefunden.(<- command not found)
... systemd[1]: jalouweb.service: Main process exited, code=exited, status=127/n/a
jalouweb.shにパスを追加すると、次のようになります。
/opt/openjdk17/bin/java -Duser.timezone=Europe/Berlin...
systemctlも成功しました。しかし、なぜ? Afaikユーザーなしでサービスを実行するとは、rootとして実行することを意味します。ルートはshとjavaを直接起動できます。 systemctlに明示的なパスが必要なのはなぜですか?
編集:私はwenshuoの提案に従いました。サービスは正常に実行されますが、tmplogファイルは生成されませんが、Journalctlは次のようになります。
systemd[1]: Started JalouWeb.
jalouweb[11189]:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin > /tmp/tmplog
systemd[1]: jalouweb.service: Succeeded.
echoコマンドが実際に正しくないようです。ただし、重要な情報は次のとおりです。非対話型ルートパスにjavaがありません。
編集2 @Stephane:スクリプトの検索または実行に問題はありません。問題は、スクリプトから呼び出されたJavaが見つからないことです。 systemctlの実行者にパスまたはJAVA_HOMEを提供する方法を理解する必要があります。
答え1
bash some-path
どこsome-path
/
次の文字は含まれていません。いいえ使用。状況が悪い場合でも、これはいくつかの異なるKorn様シェル1と組み込み.
2、source
または多くのBourne様シェルに適用されますbash
。
bash
これは、プログラミング言語のインタプリタと同様に、Bashプログラミングperl
言語のインタプリタですPerl
。
bash /path/to/some/Bash/file
標準入力のコードではなく、与えられたファイルのBash / Perlコードをperl /path/to/some/Perl/file
話すか解釈する方法bash
と同じです。perl
たとえば、次の目的に使用されます。
#! /bin/bash -
実行後、システムはそれをファイルの内容に変換して/bin/bash - path/to/the/file
解釈します。bash
そして実行中ですが、実行されません。/bin/bash some-path
systemd
bash
bash
実装する some-path
3、ちょうどそれを読み、その中のBashコードを解釈します。
今、いつsome-path
/
動作の変更は含まれていませんbash
。bash
まず、通常のパスとして解釈されるので、ここでは現在の作業ディレクトリとは対照的ですが、ファイルが見つからない場合は、$PATH
一部のデフォルト検索リストの環境変数(または設定されていない場合)のディレクトリコンポーネントでそのファイルを探します。 )。
この行動は許可するPOSIXでは必要ありませんが、POSIXでは実行可能ファイルその過程で発見されたファイル。 Bash(最小バージョン5.2)は、POSIXモードでも実行不可能なファイルを見つけて非標準にすることができます。
bash
ここでは、スクリプトがあるディレクトリでスクリプトを解釈する必要があり、次のことを行う必要があります。
WorkingDirectory=/path/to/that/dir
ExecStart=/bin/bash ./the-script
(./
パスにプレフィックスaが含まれていることを確認し、/
何らかの$PATH
理由で現在の作業ディレクトリが見つからない場合は、ルックアップを無効にしてください。)the-script
WorkingDirectory
指定しない場合、デフォルトはシステム/
サービスとユーザーのホームディレクトリです。
または、スクリプトのフルパスを指定する必要があります。
ExecStart=/bin/bash /path/to/that/dir/the-script
実行可能ファイルをインデントしてthe-script
解釈してfindとしてbash
見つけた場合は、実行権限()を持つshebangがあり、に保存されていることを$PATH
確認してください。#! /bin/bash -
chmod a+x
$PATH
systemd
そして、以下を使用してください:
ExecStart=the-script
ファイルが実行可能な場合は、拡張子を削除することをお勧めします.sh
。それ以外の場合、Bash言語で書かれている場合は、.bash
代わりに拡張機能を使用することをお勧めします。.sh
標準構文でない場合は誤解を招く可能性がありますsh
。
¹これはshまたはkshエミュレーションのzshの場合であり、kshがこのバグ機能のソースである可能性があります。
².
これは実際に特別な組み込み機能の場合はPOSIXよりも悪いです。必要 /
- 少ないパスが検索されます$PATH
(現在の作業ディレクトリに置き換えられます)。一部のシェルでは、要件は無視されます(POSIXモードでない場合はbashを含む)。
³ここにあるbash -c the-script
テキストはthe-script
bashによってインラインシェルコードとして解釈され、単純なコマンドとして解釈されるので違いがあります$PATH
。実行可能ファイルこれを行うコマンド(スクリプトまたは非スクリプト)実装する。
答え2
実行可能ファイルを見つけるために、シェルは$PATH
変数にリストされたディレクトリを検索します。$PATH
ディレクトリのパス名を含めると、実行可能ファイルのフルパス名を指定せずにそのディレクトリから実行可能ファイルを呼び出すことができます。
echo "$PATH"
シェルで現在のパスのリストを表示できます。あなたの場合は、インタラクティブシェルで使用するのとは異なる場合が$PATH
あります。systemctl
root
$PATH
次のコマンドを使用して、で使用されている値を表示できます。systemctl
ExecStart=/bin/echo "$PATH" > /tmp/tmplog
...[Service]
ユニットファイルのセクションにあります。$PATH
これにより、の値がに書き込まれます/tmp/tmplog
。