-1

I wrote a program in Java, which uses the RXTX serial port, so I had to include an additional library. At first I ran it from SSH, and it was working properly. After that, I was running some test directly on the given computer, and it also worked normally. At this point, I'm trying to make it work on the specific computer, however, with no display, and it should run automatically (I did it with crontab earlier, and I planned to use it again). So I reused an old script below.

#!/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

Which worked correctly for an another program before (that one had GUI, this one does not). I can still run it from SSH with the command behind the exec, but when I try to use shell script, it gives

-bash: [: missing `]'

And also the standard error message that I use java in the wrong way, even tough directly it still works

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

The script supposed to check if java is running, and restarting my program if it doesn't, in crontab and init.d. However, at this point it does nothing at all. (And it should be able to read from console, right? I cannot check it, since it doesn't run without a display.)

The other programs worked correctly, however they just run java -jar "file", without any additional parameters.

EDIT:

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"

Something is fishy. Trying to run with absolute java...

Ok, now it seems to work, except java is throwing error messages, because it's not able to read a new line when it is not supposed to do so. It requires an investigation, but in the Java code. Thanks for your help!

kry
  • 113
  • 6

1 Answers1

1

The script supposed to check if java is running, and restarting my program if it doesn't, in crontab and init.d. However, at this point it does nothing at all. (And it should be able to read from console, right? I cannot check it, since it doesn't run without a display.)

Why do this manually when there are existing solutions out there that do this for you. For example, if your system runs systemd or upstart you can create a service file (of upstarts equivalent) to run your java program and automatically restart it on failure. Such as with the following service file /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

Output will be captured by journalctl and can be viewed by journalctl -xfu rxtxcomm or run systemctl status rxtxcomm to see the status of the command with some log info if it fails to start.

Or if your system does not run systemd or upstart you can use something like supervisord to manage restarting your process for you.

For example in /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
...

Here logs will be written to a log file as specified in the [supervisord] section of /etc/supervisord.conf

Since you get the logs with this method you can inspect them to see why your application is actually failing to start. But I suspect it has something to do with you needing to run the headless java (which is normally a separate package you can install)


For completeness and to address some of the issues with your current script I will continue below.

-bash: [: missing `]'

The first if has probably always been slightly failing (see below for stopping this). The syntax for if in bash is if <command>; then <command>; done. [ and [[ are actually commands with some weird arguments to make it look normal in an if statement. You simply want to run a command so just include that inside the if without the [...]:

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

And also the standard error message that I use java in the wrong way, even tough directly it still works

The help message is from your use of single `s around your java as this will cause bash to execute what is within the quote and place stdout of the command in its place.

For example

echo `printf hello`

Here bash will execute printf hello then replace the whole expression with the stdout of the command simplifying it to

echo hello

Furthermore there is no need to ps | grep you can use pgrep to do it in one command:

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

Stopping scripts failing slightly

As an aside, since there are a few bugs in your program that are slightly failing.

You can stop scripts from slightly failing and thus catch more bugs in them sooner by setting some bash options at the start of the script, generally i copy paste this to all of my scripts:

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

Which causes bash to error on undefined variables, if a command in the pipe fails and print out a more useful error if any statement fails. It also changes the way bash handles space separator to be more logical. You can read up more about these settings here.

Be careful when adding this to existing script as it might cause them to stop working as quite a lot of scripts are subtle errors in them (like your original one does).

  • I wasn't aware systemd can also do this. I was thinking about using it to run the script on startup.

    I tried to use the file for systemd you wrote, (with the necessary alterations of course), but it still does not work. The journalctl says there are no journal files, and does not do anything until I cancel it with ctrl+c. I've already tried restarting the system.

    – kry Sep 18 '17 at 13:17
  • I was thinking, maybe the sudo does the problem? When I run the program without sudo, it's fine until it has to communicate through the serial port, but otherwise does it correctly. I also inlcuded the sudo in the service. The whole thing does not work without sudo. Weird, I gave all files used 777 permission, but still only works with sudo. – kry Sep 18 '17 at 13:53
  • Do not use sudo inside systemd - the scripts already run as root and if you need them to run as another use use the User=someuser directive in the service file. Sudo expect a tty to be present which is not true for things run under systemd. The service files should also have the default permissions of 0644, there is no need for them to be executable as they are just config. – Michael Daffin Sep 18 '17 at 15:56
  • I also made a mistake - you need the absolute path to java in the ExecStart directive - I have updated the answer to fix this. – Michael Daffin Sep 18 '17 at 16:01
  • If the service fails to start at all sometimes journalctl can be empty (no output from the command) you can use systemctl status <service> to get more information about the process status. – Michael Daffin Sep 18 '17 at 16:03
  • Then actually it might be not good. I need to have an input from the console, so I guess I need a tty. This program reads a card, and opens the door if valid, but should not give the user a feedback. For this reason, there is no need to have a monitor, but I still need the input console. – kry Sep 19 '17 at 06:50
  • How are users meant to see what they type if you have no monitor? Does the card reader act as a keyboard? You might want to describe your setup/application in more detail probably in a new question. You could potentially run your program as a login shell and automatically login a given user - but this would be a hacky solution with many potential issues. More details are really required about your setup/what you are trying to achieve if you want more advice. – Michael Daffin Sep 19 '17 at 08:35
  • https://unix.stackexchange.com/questions/393131/giving-data-to-programs-as-service I just posted one here. I do not need the input, the java will just send it to the server, which gives a reply to open the door or not. The computer does not actually have any keyboard or a monitor, just a barcode reader. – kry Sep 19 '17 at 08:37