web-dev-qa-db-ja.com

linux-serviceとしてのBashスクリプトは実行されませんが、ターミナルから実行すると完全に機能します

Googleドライブをマウントするカスタムスクリプトがあります。
このスクリプトの一部は次のコードです:

if [ ! "$(which google-drive-ocamlfuse)" ]
then
    echo "Install google-drive-ocamlfuse first!"
    exit 1
fi

端末から実行され、魅力のように動作します。
それで、サービスとして構成しました:

[Unit]
Description=Mount and umount google drives

[Service]
User=<usernamehere>
Type=oneshot
RemainAfterExit=true
ExecStart=/home/<usernamehere>/mybscripts/gdrivemounter.sh -m
ExecStop=/home/<usernamehere>/mybscripts/gdrivemounter.sh -u
Environment="DISPLAY=:0"
Environment="XAUTHORITY=/home/<usernamehere>/.Xauthority"

[Install]
WantedBy=graphical.target

残念ながら、終了コードが表示されます:「最初にgoogle-drive-ocamlfuseをインストールしてください!」サービスのステータスを確認するとき。

コマンドwhich google-drive-ocamlfuseユーザーとルートの下で有効なパスが得られます:

$ which google-drive-ocamlfuse
/home/<usernamehere>/.opam/default/bin/google-drive-ocamlfuse

問題はどこだ?

8
rah606

問題は、スクリプトがサービスとして実行されるときに、「あなた」として実行されないことです。つまり、環境がありません。具体的には、PATH変数がありません。

スクリプトのPATHに/home/<usernamehere>/.opam/default/binを追加するか、単にそのプログラムの完全なパスをハードコードします。

12
glenn jackman

最も可能性の高い理由は、google-drive-ocamlfuseを含むディレクトリがログインシェルのPATHにあるが、PATHが使用する標準のsystemdにはないことです。

スクリプトの先頭に次のような行を追加するだけです。

PATH=$PATH:/path/to/google-drive-ocamlfuse
3
RalfFriedl

解決策をありがとうございました。それぞれが私にとって重要であり、役立つものです。ここでも、新しいことを学びました。最後に、opamではなく、debからgoogle-drive-ocamlfuseをインストールすることにしました。すべてのユーザーが使用できるパスにgdoをインストールすることをお勧めします。このため、$ PATHの追加構成は必要ありません。

1
rah606

注:この回答は「現状のまま」残しましたが、唯一の関連性があります一部は、スクリプトで直接ではなく、サービスファイルを介して環境を設定する方法です。スクリプトの新しい$ PATHの設定は、スクリプトの実行が終了すると保持されません。

他の回答を参考にして、スクリプトを編集して$PATHを汚さないでください。実際、正しいユーザーが実行した場合は機能します。スクリプトで直接編集する必要がある場合は、元の$PATHを復元して元に戻します。

問題は、/ etc/profileがsystemdサービスによって処理されないため、何らかの理由で必要な実行可能ファイルへのアクセス(または更新された$ PATH)が得られないことにあると思います。

これをテストするには、エラーブロック内で$ PATHをエコー出力し、ISがない場合は、systemdサービスファイル内の環境変数に直接追加します。

[Service]
Environment=PATH=/home/someUser/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

このように、パスはスクリプトの実行中にのみ更新され、変更されることを予期していない可能性のあるユーザーに対しては変更されません。