我用 Java 编写了一个程序,它使用 RXTX 串行端口,因此我必须包含一个额外的库。起初我通过 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 运行它,但是当我尝试使用 shell 脚本时,它给出
-bash: [: missing `]'
还有我以错误的方式使用 java 的标准错误消息,即使直接困难它仍然有效
sudo java -Djava.library.path=/usr/lib/jni -cp /usr/share/java/RXTXcomm.jar -jar '/foo/bar.jar'
该脚本应该在 crontab 和 init.d 中检查 java 是否正在运行,如果没有运行则重新启动我的程序。然而,此时它什么也没做。 (它应该能够从控制台读取,对吗?我无法检查它,因为它在没有显示器的情况下无法运行。)
其他程序工作正常,但是它们只是运行 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
该脚本应该在 crontab 和 init.d 中检查 java 是否正在运行,如果没有运行则重新启动我的程序。然而,此时它什么也没做。 (它应该能够从控制台读取,对吗?我无法检查它,因为它在没有显示器的情况下无法运行。)
既然已有解决方案可以为您执行此操作,为什么还要手动执行此操作呢?例如,如果您的系统运行 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
输出将由journalctl捕获,并且可以通过查看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
由于您使用此方法获取日志,因此您可以检查它们以了解应用程序实际上无法启动的原因。但我怀疑这与您需要运行 headless java 有关(通常是您可以安装的单独软件包)
为了完整性并解决当前脚本的一些问题,我将在下面继续。
-bash: [: missing `]'
第一个 if 可能总是稍微失败(请参阅下文以停止此操作)。if
bash 中的语法是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 执行引号内的内容并将命令的 stdout 放在其位置。
例如
echo `printf hello`
这里 bash 将执行,printf hello
然后将整个表达式替换为命令的标准输出,将其简化为
echo hello
ps | grep
此外,您无需使用pgrep
一个命令即可完成此操作:
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 处理空格分隔符的方式,使其更加符合逻辑。您可以阅读有关这些设置的更多信息这里。
将其添加到现有脚本时要小心,因为这可能会导致它们停止工作,因为很多脚本中都有细微的错误(就像您的原始脚本一样)。