web-dev-qa-db-ja.com

systemdと端末起動プログラムの違い

この違いがプログラム間で何であるかについて私は興味があります。 systemctlで有効にしたときにsystemdで開始した場合と、/etc/rc.localまたはCLIで開始した場合の比較.

たとえば、私は最近、Raspberry Piにshairport-syncを使用していました。最初に、Sudo systemctl enabled shairport-syncを使用してshairport-syncを開始するように設定しました。

後で、shairport-sync内の機能を使用して、接続するデバイスに事前およびポストしてスクリプトを実行しました。

驚いたことに、shairport-syncによって実行されたスクリプトはkillarecordまたはaplayを実行しませんでした

しかし、ターミナルからスクリプトを実行すると、スクリプトが実行され、arecordaplayが強制終了されました。

さらに混乱させるために、私はshairport-syncを強制終了し、ターミナルから起動して、何が起こっているのかを確認しました。そうすると、デバイスが接続してarecordaplayを強制終了したときにスクリプトが期待どおりに機能しました。そこで、修正としてsysmtectlshairport-syncを無効にし、/etc/rc.localで実行するように設定しました。 rebootの後は、期待通りに機能しました。

これにより、systemdの一部として実行されるプログラムと、/etc/rc.localまたはCLIから起動したときに実行されるプログラムには、いくつかの違いがあると私は思います。

なぜこれが起こるのですか?これは、実行レベルが異なるためですか?ダークマジック?

デバイスがshairport-syncに接続するときに実行されるスクリプトは次のとおりです:shairportstart.sh

#!/bin/sh
/usr/bin/Sudo /bin/pkill arecord
if [ $(date +%H) -ge "18" -o $(date +%H) -le "7" ]; then
        /usr/bin/amixer set Speaker 40%
else
        /usr/bin/amixer set Speaker 100%
fi
/home/pi/shScripts/shairportfade.sh&

exit 0

これがフェードスクリプトです:shairportfade.sh

#!/bin/sh
/usr/bin/amixer set Speaker 30-
for (( i=0; i<30; i++))
do  
    /usr/bin/amixer set Speaker 1+
done
exit 0

デバイスがshairport-syncに切断したときに実行されるスクリプトは次のとおりです:shairportend.sh

#!/bin/sh
/usr/bin/amixer set Speaker 70%
/usr/bin/arecord -D plughw:1 -f dat | /usr/bin/aplay -D plughw:1 -f dat&
exit 0

systemdの一部としてshairport-syncが最初に実行されたときにのみ、/var/log/syslogに次のエラーが見つかりました。 shairport-syncがCLIまたは/etc/rc.localから実行されたとき、エラーはありませんでした。

Jan 24 00:38:45 raspberrypi shairport-sync[617]: Sudo: no tty present and no askpass program specified

唯一の違いは、デバイスが接続または切断したときにshairport-syncが最初にどのように開始されるかであり、shairport-syncが引き続き実行されることに注意してください。

9
Brett Reinhard

「systemdでの動作が異なるのはなぜですか?」のバリエーションはよくある質問です。

SystemdからではなくCLIから何かが実行されるときはいつでも、違いを説明する可能性のいくつかの広いカテゴリーがあります。

  1. 異なる環境変数systemdは、それが渡す環境変数を_man systemd.exec_でセクション 生成されたプロセスの環境変数 に記述します。違いを自分で調べたい場合は、_systemd-run /path/to/binary_を使用できます。これは、systemdサービスによって実行されるため、アプリを一時的なスコープで実行します。 _Running as unit: run-u160.service_のような出力が得られます。次に、_journalctl -u run-u160.service_を使用して出力を確認できます。アプリを変更して、受け取った環境変数をダンプし、CLIの実行とsystemdの実行を比較します。アプリが適切に変更されていない場合は、_systemd-run env_を使用して渡される環境変数を確認し、その結果のジャーナルログを確認できます。 X11 GUIアプリを起動しようとしている場合は、 DISPLAY環境変数を設定する必要があります 。その場合は、systemdではなく、デスクトップ環境の「自動起動」機能の使用を検討してください。
  2. リソース制限。リソースの消費を制限する可能性のある設定値については、 _man systemd.resource-control_ を参照してください。 _systemctl show your-unit-unit.service_を使用して、開始しようとしているサービスに影響を与える完全な構成値を確認します。
  3. 非インタラクティブシェルbash CLI環境は対話型ログインシェルです。 systemdにはない_.bashrc_などのソースファイルがあります。これらのスクリプトは、環境変数の設定に加えて、SSHエージェントが接続してSSHアクションがログインを必要としないようにするなど、他の多くのことを実行できます。参照 ログインシェルと非ログインシェルの違い?
  4. TTYなし。インタラクティブセッションは、Sudosshなどの一部のプログラムがパスワードを要求するときに予期するTTYに接続されています。参照 Sudo:ttyが存在せず、askpassプログラムが指定されていない
  5. 相対パスと絶対パス。シェルでは相対バイナリが機能しますが、 _man systemd.service_ に記載されているように、_ExecStart=_の最初の引数はバイナリへの絶対パスである必要があります。
  6. 制限されたコマンドライン構文。シェルCLIは多くのメタ文字をサポートしていますが、 systemdのコマンドライン構文は非常に制限されています です。必要に応じて、シェルからコマンドを明示的に実行することにより、systemdを使用してシェル構文を複製できる場合があります。ExecStart=/bin/bash -c '/my/bash $(syntax) >/goes-here.txt'

これは、システムがリソース制御を備えた一貫した環境でコードを実行する機能です。これにより、ハードウェアを圧倒することなく、長期的に再現性のある安定した結果を得ることができます。

17
Mark Stosberg