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


9

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

たとえば、私は最近、ラズベリーパイにshairport-syncを使用していました。最初に、sudo systemctl enabled shairport-syncを使用してshairport-syncを開始するように設定しました。

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

驚いたことに、スクリプトが実行されshairport-syncたときkill arecordaplay

しかし、私はスクリプトが実行され、殺された端子を介してスクリプトを実行しますarecordaplay

さらに混乱させるために、私shairport-syncはそれを強制終了し、ターミナルを介して起動して、何が起こっているかの出力を確認しました。私はそのようにしたときのスクリプトは、デバイスが接続されて殺されたときに、私は期待通りに機能arecordしてaplay。だから、修正として私は無効shairport-syncsysmtectlしてで実行するように設定する/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

/var/log/syslog最初にshairport-syncをの一部として実行したときにのみ、次のエラーが見つかりましたsystemdshairport-syncCLIから実行した場合、または/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が実行され続ける場合の最初の起動方法だけであることに注意してください。


1
そのps ... awk ... grep ...ようなものは、より単純なものに置き換えられる可能性がありますpkill
2017年

@thrigはもともと行がはるかに単純でしたが、機能しなかったため、他の方法を使用して、まだ機能しないインスタンスを強制終了しようと思いました。プロセスを強制終了すること自体は問題ではなく、機能しましたが、ユーザーログインから実行した場合に限られます
Brett Reinhard

のリストを表示できます/home/pi/shScripts/shairportfade.shか?
マイケルD.

@MichaelD。フェードスクリプトと、デバイスがshairport-syncに切断したときに実行されるスクリプトを追加しました
Brett Reinhard

@BrettReinhardからスクリプトを実行する際の問題は何ですかrc.local
マイケルD.

回答:


18

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

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

  1. 異なる環境変数systemd渡される環境変数については、「生成されたプロセスの環境変数」man systemd.execセクションを参照してください。違いを自分で調べたい場合は、を使用できます。systemdサービスによって実行されるため、一時的なスコープでアプリが実行されます。次のような出力が得られます。その後、出力を確認できます。アプリを変更して、受け取った環境変数をダンプし、CLIの実行とsystemdの実行を比較します。アプリが適切に変更されていない場合は、を使用して、渡される環境変数を確認し、その結果のジャーナルログを確認できます。X11 GUIアプリを起動しようとしている場合は、環境変数を設定する必要がありますsystemd-run /path/to/binaryRunning as unit: run-u160.servicejournalctl -u run-u160.servicesystemd-run envDISPLAY。その場合は、デスクトップ環境の「自動起動」機能を使用することを検討してくださいsystemd
  2. リソース制限man systemd.resource-controlリソースの消費を制限する可能性のある設定値については、を参照してください。systemctl show your-unit-unit.service開始しようとしているサービスに影響を与える完全な構成値を確認するために使用します。
  3. 非対話型シェル。あなたのbashCLI環境は、対話型ログインシェル。それはのようなファイルをソースしていない持っています。これらのスクリプトは、環境変数を設定するだけでなく、SSHエージェントに接続するなど、SSHアクションにログインが必要ないようにするなど、さまざまなことを実行できます。ログインシェルと非ログインシェルの違いも参照してください.bashrcsystemd
  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'

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


また、MACコンテキスト(SELinuxなど)、機能、名前空間も考慮する必要があります
Bigon

2
@BrettReinhard systemdはスクリプトをrootとして実行しているため、ターミナルからsudo実行するシェルスクリプトを呼び出さないでください。sudo sudo shairportstart.shをrootとして実行する必要はありません。
マイケルD.

1
何が起こっているのかを理解するために、私は複数の方法で問題を解決しました。最終的に、私がやったことは、killコマンドをに変更することでした/usr/bin/echo "mypassword" | /usr/bin/sudo /bin/pkill arecord。今日の後で、killコマンドからsudoおよびechoコマンドを削除して、同じ結果が得られるかどうかを確認します。sudoコマンドでパスワードが送信されなかったためにエラーが発生したと思われるので、うまくいくと思います。systemdとCLIに違いがある理由を理解していただきありがとうございます
Brett Reinhard

1
もう1つの違いは明白かもしれませんが、今日は私を悩ませていますが、systemdはサービスのステータスを追跡しようとし、すでにアクティブであると思われる場合はサービスを開始しないので、サービスが実行されていると考えます。対照的に、init.dスクリプトは通常、常にサービスをチェックし、必要に応じてサービスを開始しようとするように記述されています。
ジョシュケリー

1
@JoshKelley先端をありがとう。これはsystemdとCLIの違いではなく、systemdとsysVinit init.dスクリプトの違いです。
Mark Stosberg、2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.