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 코드로 진행됩니다. 당신의 도움을 주셔서 감사합니다!
답변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는 항상 약간 실패할 수 있습니다(이를 중지하려면 아래 참조). 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가 따옴표 안에 있는 내용을 실행하고 해당 위치에 명령의 표준 출력을 넣게 됩니다.
예를 들어
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가 공백 구분 기호를 처리하는 방식을 변경하여 더욱 논리적으로 만듭니다. 이 설정에 대해 자세히 알아볼 수 있습니다.여기.
기존 스크립트에 이를 추가할 때 주의하십시오. 이로 인해 작동이 중단될 수 있습니다. 많은 스크립트에는 미묘한 오류가 있기 때문입니다(원래 스크립트와 마찬가지로).