systemdがデーモンを実行する前に、シンボリックリンクのターゲットを作成または変更する必要があります。デーモンは標準出力をこのシンボリックリンクにリダイレクトし、それによって開始された各デーモンの特殊ファイルにリダイレクトします。これが私たちが考えるものです。 「test_start.service」というサービス単位ファイルを設定しました。
[Unit]
Description=Test Server
After=network-online.target test_start.socket
Requires=network-online.target test_start.socket
[Service]
User=test1
Group=test1
Type=simple
ExecStartPre=/bin/bash /etc/testServer/Debug/makeOutfile.sh
ExecStart=/etc/testServer/Debug/testServer
StandardInput=socket
StandardOutput=file:/etc/testServer/Debug/test_outLink
Restart=on-failure
RestartSec=3
[Install]
WantedBy=multi-user.target
Bashスクリプト "/etc/testServer/Debug/makeOutfile.sh"は次のようになります。
#!/usr/bin/env bash
timeStamp=$(date +%y-%m-%d_%Hh%Mm%Ss)
myfolder="/etc/testServer/Debug"
# create new logfile
touch $myfolder/started_$timeStamp
# remove old symlink if exists (owned by test1)
if [ -h $myfolder/test_outLink ]; then
rm $myfolder/test_outLink
fi
# create new symlink
ln -s $myfolder/started_$timeStamp $myfolder/test_outLink
場合によっては動作します。シンボリックリンクが存在し、それが指すファイルも存在する場合、すべてが正常です。 bashスクリプト "makeOutfile.sh"は、テスト用の端末とsystemdサービスの起動を通じて実行されます。
しかし:
(名前: "started_atSomeDate")指すファイルが存在しない場合(誰かがその間に削除したため)、スクリプトのターミナル呼び出しは期待どおりに機能しますが、systemdサービスを開始すると、所有した追加ファイルが追加されます。元の古いファイル名が「started_atSomeDate」のルートルートです。
これはどこから来たのですか?
以前のシンボリックリンク「test_outLink」が存在しない場合(誰かが途中で削除したため)、スクリプトの端末呼び出しは期待どおりに機能しますが、systemdサービスを開始すると、新しく作成された「test_outLink」が通常のファイルとして追加されます。ルートグループを持つルートが所有しており、サービスを開始できません。
ここに深刻な問題があります。 systemd サービス単位 ユーザーとグループが test1 で、ここにルートが混在しています。誰でもこれを説明できますか?私は何が間違っていましたか?
答え1
私の提案は、シェルスクリプトを使用してログファイルを設定する必要があることです。そして適切なリダイレクトでテストサーバーを実行して、StandardOutput=
ケースに適用されないシステム設定をバイパスします。
次のようなbashスクリプトを作成します/etc/testServer/Debug/runTestServer.sh
。
#!/usr/bin/env bash
timeStamp=$(date +%y-%m-%d_%Hh%Mm%Ss)
myfolder="/etc/testServer/Debug"
# create new logfile
touch $myfolder/started_$timeStamp
# remove old symlink if exists (owned by test1)
if [ -h $myfolder/test_outLink ]; then
rm $myfolder/test_outLink
fi
# create new symlink
ln -s $myfolder/started_$timeStamp $myfolder/test_outLink
# run the actual testServer
exec /etc/testServer/Debug/testServer >/etc/testServer/Debug/test_outLink
元のスクリプトとの唯一の違いmakeOutfile.sh
は、このスクリプトがtestServer
適切なリダイレクトを使用して実行され、標準出力を設定したログファイルに送信することです。
exec
また、シェルスクリプトが保持または置換されないようにするためにも使用されますtestServer
(それで、systemdはサービスの主なプロセスが何であるかを知ることができます)。
ユニットファイルからファイルを削除し、次のファイルにExecStartPre=
置き換えStandardOutput=
ますExecStart=
。
ExecStart=/etc/testServer/Debug/runTestServer.sh
(代わりにスクリプトを呼び出すことも/bin/bash
可能ですが、スクリプトに実行可能なビットが設定されている限り、必ずしも必要ではありません。)
このようなスクリプトでサーバーを設定すると、シンボリックリンクを完全に迂回して最終started_$timeStamp
ログファイルに直接リダイレクトすることもできます。
私はsystemdコードを直接見ていないし、ドキュメントが互いにどのようにやり取りするのか正確にはわかりません。しかし、systemdがステップを実行する順序と、どのプロセスがそれを実行するのかについては間違いなく問題がありますStandardOutput=
。ExecStartPre=
、これは権利/所有権を変えます。)したがって、あなたが報告した結果にあまり驚かないことに注意してください。とにかく私の提案は、単一のラッパーランチャースクリプトを使用して単純化することです。したがって、問題が解決することを願っています。