シェルスクリプトはJavaを実行せず、パラメータが無効です。

シェルスクリプトはJavaを実行せず、パラメータが無効です。

RXTXシリアルポートを使用するプログラムをJavaで書いたので、追加のライブラリを含める必要がありました。最初はSSH経由で実行しましたが、うまくいきました。その後、特定のコンピュータで直接いくつかのテストを実行しましたが、それもうまくいきました。この時点で特定のコンピュータで動作しようとしていますが、表示されずに自動的に実行する必要があります(crontabを使用する前にやったことがあり、再利用する予定です)。だから、以下の古いスクリプトを再利用しました。

#!/bin/bash

if [ ps x $UID | grep -v grep | grep -c `java` ]; then # process fut, nem kell semmi
    exit 0;
else
#   export DISPLAY=:0;
    exec sudo java -Djava.library.path=/usr/lib/jni -cp /usr/share/java/RXTXcomm.jar -jar '/foo/bar.jar';
fi

pidof java
if [[ $? -ne 0 ]] ; then
    #export DISPLAY=:0
    exec sudo java -Djava.library.path=/usr/lib/jni -cp /usr/share/java/RXTXcomm.jar -jar '/foo/bar.jar' &
fi

以前、他のプログラムはうまく機能しました(そのプログラムにはGUIがありましたが、このプログラムにはありませんでした)。 execコマンドを使用してSSHで実行することはできますが、シェルスクリプトを使用しようとすると、次の結果が表示されます。

-bash: [: missing `]'

また、Javaを間違った方法で使用していますが、直接的に難しい場合でも動作します。

sudo java -Djava.library.path=/usr/lib/jni -cp /usr/share/java/RXTXcomm.jar -jar '/foo/bar.jar'

スクリプトは、Javaが実行されている場合はcrontabとinit.dを確認し、そうでない場合は私のプログラムを再起動する必要があります。ただし、この時点では何もしません。 (コンソールで読むことができますか?モニターなしでは実行されていないため確認できません。)

他のプログラムはうまく機能しますが、追加の引数なしでjava -jar "file"だけを実行します。

編集する:

Sep 18 14:03:38 raspberrypi systemd[1]: [/etc/systemd/system/rxtxcomm.service:4] Executable path is not absolute, ignoring: java -Djava.library.path=/usr/lib/jni -cp /usr/share/java/RXTXcomm.jar -jar "/home/pi/forgokapu/dist/forgokapu.jar"

何か怪しいことがあります。絶対にJavaで実行してみてください...

さて、今動作しているようです。ただし、Javaが新しい行を読み取らないと読み取れないため、エラーメッセージが発生することを除いてください。調査が必要ですが、Javaコードに進みます。ご協力ありがとうございます!

答え1

スクリプトは、Javaが実行されている場合はcrontabとinit.dを確認し、そうでない場合は私のプログラムを再起動する必要があります。ただし、この時点では何もしません。 (コンソールで読むことができますか?モニターなしでは実行されていないため確認できません。)

これを行うソリューションがすでにありますが、なぜ手動で実行するのですか?たとえば、システムがsystemdまたはupstartを実行している場合は、サービスファイル(upstartsと同じ)を生成してJavaプログラムを実行し、失敗したときに自動的に再起動できます。たとえば、次のサービスファイルは次のとおりです/etc/systemd/system/rxtxcomm.service

[Unit]
Description=RXTXcomm
[Service]
ExecStart=/usr/bin/java -Djava.library.path=/usr/lib/jni -cp /usr/share/java/RXTXcomm.jar -jar '/foo/bar.jar'
Type=simple
Restart=always
[Install]
WantedBy=multi-user.target

出力はジャーナルctlによってキャプチャーされ、開始に失敗した場合は、コマンドの状況、およびいくつかのログ情報を確認するために表示またはjournalctl -xfu rxtxcomm実行できます。systemctl status rxtxcomm

あるいは、システムがsystemdまたはupstartで実行されていない場合は、次のものを使用できます。監督者プロセスの再起動が自動的に管理されます。

たとえば、次のようになります/etc/supervisord.conf

...
[program:rxtxcomm]
command=/usr/bin/java -Djava.library.path=/usr/lib/jni -cp /usr/share/java/RXTXcomm.jar -jar '/foo/bar.jar'
autostart=true
autorestart=true
...

このログは、次のセクションで指定されたログファイル[supervisord]に書き込まれます。/etc/supervisord.conf

この方法を使用してログをインポートするので、ログを調べてアプリケーションが実際に起動しない理由を確認できます。しかし、私はこれがヘッドレスJava(通常はインストールできる別々のパッケージ)を実行する必要があることに関連していると思います。


完全性を期し、現在のスクリプトのいくつかの問題を解決するために以下に進みます。

-bash: [: missing `]'

最初のifは常にわずかに失敗する可能性があります(これを停止するには以下を参照)。ifBashの構文は、if <command>; then <command>; done実際にifステートメントで正常に見えるようにする奇妙な引数を含むコマンド[です。[[単一のコマンドだけを実行したいので、if次のことなくコマンドを内部に含めることができます[...]

if ps x $UID | grep -v grep | grep -c 'java'; then # process fut, nem kell semmi

また、Javaを間違った方法で使用していますが、直接的に難しい場合でも動作します。

ヘルプメッセージは、Javaの周りに単一の `s を使用して表示されます。これにより、bashは引用符内の内容を実行し、その場所にコマンドの標準出力を配置します。

例えば

echo `printf hello`

ここでbashは、実行された次のprintf hello式全体をコマンドの標準出力に置き換えて、次のように短縮します。

echo hello

ps | greppgrepまた、これを行うために単一のコマンドを使用する必要はありません。

if pgrep -U "$UID" "java"; then ...; done

停止スクリプトが少し失敗する

ちなみに、プログラムのいくつかのバグのために少し失敗します。

スクリプトが少し失敗するのを防ぐために、スクリプトの先頭にいくつかのbashオプションを設定すると、より速くより多くのエラーをキャッチできます。通常、私はこれをすべてのスクリプトにコピーして貼り付けます。

#!/bin/bash
set -uo pipefail
trap 's=$?; echo "$0: Error on line "$LINENO": $BASH_COMMAND"; exit $s' ERR
IFS=$'\n\t'

これにより、パイプラインのコマンドが失敗した場合、未定義の変数に対してbashでエラーが発生し、ステートメントが失敗すると、より便利なエラーが出力されます。また、bash がスペース区切り文字を処理する方法を変更して、より論理的にします。この設定の詳細をご覧ください。ここ

既存のスクリプトにこれを追加するときは注意してください。これにより操作が中断される可能性があります。多くのスクリプトには微妙なエラーがあるためです(元のスクリプトと同様)。

関連情報