web-dev-qa-db-ja.com

ログインしたかのようにsystemdからbashスクリプトを実行する

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について何がわからないのですか?

1
Jim B.

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でサービスを実行する方法を尋ねる必要があります。

1
Mark Stosberg