Synology Scheduler .sh java command not found
Asked Answered
P

2

11

I have a bash script thats only task is to execute a jar file.

sms.sh

java -jar /volume1/homes/jar/smssender.jar

Using my Synology NAS I set up a task.

Task Setup run by root

Adding the command to execute bash script. Adding log output.

enter image description here

Executing my new Task.

enter image description here

Checking the log to see the following error:

/volume1/homes/jar/sms.sh: line 1: java: command not found

Checking Java version/installation:

enter image description here

Checking execution of sh script manually (working):

enter image description here

Anyone with this same strange case? Any workarounds/ideas?

I tried

  • Rebooting my NAS
  • Uninstall / install Java8 package

but none worked.

Persecution answered 2/2, 2020 at 14:34 Comment(5)
Given your problem, it is probably a problem with a env (JAVA_HOME, PATH) not correctly set when the job is executed. You should either use absolute path to java executable, either source a file doing that for you.Williwaw
@Williwaw What do you mean with absolute path? Isnt /volume1/(...)/file.jar the path? Thank you for help and timePersecution
First, find the java executable. Then, invoke it using /whatever/path/to/java/is/java /volume1/homes/jar (this is not specific to synology)Williwaw
We should probably add here that whatever user is running the command eventually is probably not the user that OP is logging in with (unless he's sure it is), and therefore has a different PATH.Mose
(Also: is this really on-topic?)Mose
S
9

When the Synology task scheduler executes the script sms.sh the PATH setting is taken from script /etc/crontab. Which does not contain the Java path.

The default login shell environment is defined int /etc/profile. At the end there is a section to add the Java path.

PATH=$PATH:/var/packages/Java8/target/j2sdk-image/bin # Synology Java runtime enviroment
PATH=$PATH:/var/packages/Java8/target/j2sdk-image/jre/bin # Synology Java runtime enviroment
JAVA_HOME=/var/packages/Java8/target/j2sdk-image/jre # Synology Java runtime enviroment
CLASSPATH=.:/var/packages/Java8/target/j2sdk-image/jre/lib # Synology Java runtime enviroment
LANG=en_US.utf8 # Synology Java runtime enviroment
export CLASSPATH PATH JAVA_HOME LANG # Synology Java runtime enviroment

As already stated in already given comments sourcing a profile script which is meant for an interactive shell isn't suggested. You might mimic the behavior of the /etc/profile script in your sms.sh script to set CLASSPATH PATH JAVA_HOME LANG.

The raised points about hardcoding the path in your script and the resulting reduced portability might have a lover precedence in this specific case.

Superfluid answered 12/2, 2020 at 1:20 Comment(2)
Your answer helped me a lot and is correct but I missclicked on my phone and gave the 100 points to the user down under. I am really sorryPersecution
@Persecution That's live. ;-)Superfluid
S
0

I'm not familiar with Synology so fwiw ...

The shell script works when executed at the command line because the particular login session has already loaded a set of environment variables (eg, upon logging in the .profile/.bashrc script(s) in the home directory is sourced and the various java-specific environment variables are loaded - PATH, JAVA_HOME, CLASSPATH, etc) that allow java and the script to run without issue.

The failed Synology job error indicates that the java-specific environment variables have not been loaded and therefore the job/script is unable to locate java.

Assuming Synology does not have a configuration setting/flag that stipulates to pre-load a login's profile, the 'easy' solution would be to edit the script (sms.sh) and have it source the appropriate resource file before performing any operations (eg, calling java). A simple example:

$cat sms.sh
#!/usr/bin/bash

. ~root/.bashrc      # load the root account profile before continuing ...

java ...

NOTES:

  • replace root with the name of the login under which the script is to be run (in the example Synology images it appears you've chosen the root user hence my example references ~root)
  • replace ~root/.bashrc with the path to user's profile in order to pre-load the environment variables needed to allow the script to find java
Scaphoid answered 9/2, 2020 at 17:10 Comment(4)
Please don't encourage config files written for interactive use to be used in noninteractive contexts -- it leads so situations where people think changes they're making are harmless (because .bashrc doesn't change how daemons operate, right?) but can instead cause production breakage.Adductor
Much better to find the real location and just hardcode an appropriate PATH update in the script itself, or in a dedicated-purpose configuration file the script sources. That also works in situations where this won't -- f/e, when /etc/profile.d rather than ~/.bashrc is relevant.Adductor
hardcoding is hardly portable, especially in mixed OS/version environments; as for using interactive config/resource files vs specially-built resource/config files ... that's more of a personal choice issue based on the developer(s) writing/maintaining the environment; I've had no/zero problems over the last 20 years ...in production environments ... using a common resource/config file across an entire scripting env, ymmvScaphoid
Dotting in a user's interactive files isn't portable either (particularly given how distros rebalance which content is done by which files -- some doing things the traditional way and using .profile, some using .bash_profile, some using /etc/profile.d, some setting environment variables from PAM, etc). One way or another, you're doing something nonportable. At least hardcoding PATH=$PATH:/whatever/specific/location is amending to settings, and its behavior is obvious to readers (who don't need to worry about whether it'll change later).Adductor

© 2022 - 2024 — McMap. All rights reserved.