Bashスクリプトとして実装されたサービスがあります。内部には実際にはnode.jsアプリケーションがありますが、この質問の目的には何でもかまいません。
基本的なユースケースは、インタラクティブシェルでスクリプトを開発/デバッグしてから、サービスとして有効にすることです。
デバイスにssh(ログイン)して環境全体がそこにあり、コマンドラインでスクリプトを起動できる場合は問題ありません。私がいるシェルは、.bashrc
、.profile
などから適切な環境を選択し、すべてが機能します。
しかし、systemdサービスから起動すると、インタラクティブシェルの場合と同じようにsource
環境になります。ユニットに環境変数を追加するための規定がありますが、ここで行っていることは、インタラクティブ環境が行うことを複製するだけで、何かを忘れる簡単な方法になります。
実際の本番サービスの場合、これを行う正しい方法があると確信していますが、これはラボアプリケーションであり、スクリプトで作業する人がsystemdの動作を知る必要がないように簡単にする必要があります。
だから質問:インタラクティブなBashシェルで実行するようにスクリプトを記述してsystemdから実行するにはどうすればよいですか?
--login
でbashを起動しようとしましたが、機能しません。また、外部スクリプトでsource .bashrc
を明示的に実行することもありません。
問題を強調するために私が取り組んでいる例を次に示します。
コアスクリプト(job.sh
):
#!/bin/bash
cd
while [ 1 ]
do
pwd
echo USER is $USER
echo PATH is $PATH
which node
node --version
sleep 1
done
別のスクリプトから呼び出します(wrapper.sh
):
#!/bin/bash
echo starting wrapper...
bash --login /home/droid/job.sh
これがjob.service
の/etc/systemd/system/job.service
ユニットです。
[Unit]
Description=Job Daemon
[Service]
User=droid
ExecStart=/home/droid/wrapper.sh
[Install]
WantedBy=multi-user.target
これを機能させるのを妨げるsystemdについて何がわからないのですか?
systemd
を介してスクリプトを実行することと、スクリプトを直接実行することの違いは、環境です。このようにテストできます。テストのために、Unitファイルで、これを[Service]セクションに追加します。
StandardOutput=console
次に、bashスクリプトの上部に、次の行を追加して環境をダンプします。
env
次に、systemdの内外でスクリプトを実行し、ダンプされた環境変数を比較します。
これは、環境を厳密に制御するsystemdの機能です。これにより、セキュリティが向上し、一貫性が提供されます。
Systemdが環境を管理する方法の詳細については、 systemd.exec を参照してください。
Systemdから希望どおりに実行すると、CLIとシステムを介して同じものを実行するのは簡単です。次のようにCLIを介して実行します。
systemctl start your-unit-name
その後、systemdはまったく同じ環境で実行されます。
あなたは反対のことを求めました:systemdにあなたの「bash」環境を使ってサービスを実行させること。しかし、それは厄介で変化する環境であり、一貫性のない結果につながる可能性があります。対照的に、systemdランタイム環境は厳密に制御され、一貫性のある再現可能な結果を生成します。そのため、質問を裏返し、systemdが使用するのと同じ一貫性のある制御された実行環境を使用してCLIでサービスを実行する方法を尋ねる必要があります。