2
votes

HELP!

I'm using the built-in launch script with SpringBoot 1.3.6 and Gradle. Oh, and the distZip task to zip things up.

At one point not long ago, this was all working quite well... then I did -- I know not what -- to screw it up.

I've installed the package (unzipped the Zip, basically) on my raspberry Pi, and checked the ownership and permissions. Everything is owned by the user I want to run the app as (user "appservice" group "pi") and confirmed that the permissions for the files are -- if anything, too permissive (755 for the myapp/bin/myapp script and pretty much everything else).

I've put a symlink in /etc/init.d pointing to ~appservice/myapp/bin/myapp and I've run update-rc.d myapp defaults to get it into the system. Note the symlink itself is owned by root/root, but I believe it's supposed to be, isn't it?

I'm seeing two problems, that I think are interrelated.

First, no matter how I launch the script (on boot with init.d or manually with "sudo service myapp start"), it appears to run as root (specifically, paths that the app is trying to use to access files come out as /root/myapp/files instead of /home/appservice/myapp/files).

Second, the app will crash... specifically I get the syslog message "myapp.service start operation timed out. Terminating." followed by what looks like an orderly shutdown of the app. Oh, and related... if I launch with "sudo service myapp start" the command never returns. Which is new...

Third, the application log output is going to /var/log/syslog instead of to /var/log/myapp.log which seems counter to what the Spring Boot documentation says.

I'm in final regression testing of deployment for this, and (famous last words) I haven't changed anything recently... :) No, really, the most recent change relevant to distribution was adding the src/main/dist directory, and it was working after that (launching at boot as the correct user).

I'd post the launch script but AFAIK it's the default script provided by Spring Boot when you use the springBoot { executable = true } task.

Here's my full build.gradle file... I don't see anything amiss, but maybe you will.

    buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.6.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'
apply plugin: 'application'

apply from: 'gradle/gradle/helpers.gradle'

mainClassName = 'app.Application'

if (!hasProperty('mainClass')) {
    ext.mainClass = 'app.Application'
}

springBoot {
    executable = true
}

repositories {
    mavenCentral()
}

sourceSets {
  main {
    java      { srcDir 'src/main/java' }
    resources { srcDir '/src/main/resources' }
  }
  test {
    java      { srcDir 'src/test/java' }
    resources { srcDir 'src/test/resources' }
  }
}

project.ext {
  applicationVersion = "0.1.5-alpha"

  applicationRelease = isApplicationRelease()
  applicationDate = new Date()
  applicationRevision = getRevision()

  applicationVersionSnapshot = (!applicationRelease) ? "+SNAPSHOT.${asUTC(applicationDate, 'yyMMddHHmm')}.git${applicationRevision}" : ""
  applicationVersionFull = "${applicationVersion}${applicationVersionSnapshot}"
}

jar {
    baseName = 'myapp'
    version = '0.9.0'
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {

    compile group: 'com.sun.mail', name: 'javax.mail', version: '1.5.2'
    compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.3.6'
    compile group: 'commons-cli', name:'commons-cli', version: '1.3.1'
    compile group: 'org.json', name:'json', version: '20140107'

    compile "commons-codec:commons-codec:1.10"

    compile("org.springframework.boot:spring-boot-starter-hateoas")
    compile("org.springframework.boot:spring-boot-starter-web")
    compile("org.springframework.boot:spring-boot-starter-thymeleaf")
    compile("org.springframework.boot:spring-boot-starter-mail")
    compile("org.springframework.boot:spring-boot-starter-security")
    compile("org.springframework:spring-web")
    compile("org.springframework:spring-messaging")
    compile("joda-time:joda-time:2.2")
    compile("com.fasterxml.jackson.core:jackson-databind")
    compile("com.googlecode.json-simple:json-simple")
    compile("org.jdom:jdom:2.0.0")
    compile("org.hibernate:hibernate-validator")
    compile("org.apache.tomcat.embed:tomcat-embed-el")
    compile("org.apache.commons:commons-io:1.3.2")
    compile("org.kamranzafar:jtar:2.3")
    compile("org.thymeleaf.extras:thymeleaf-extras-springsecurity4")
    compile("com.jcraft:jsch:0.1.53")
    compile("javax.jmdns:jmdns:3.4.1")
    testCompile("org.springframework.boot:spring-boot-starter-test")


}

task wrapper(type: Wrapper) {
    gradleVersion = '2.14'
}
1
Another bit of weirdness that may be related and which seems to point to some kind of user/group/permissions screwup... when i scp the zip file over, it ends up being in user/group appservice/appservice. when I try to chgrp the files to group ip, I get "operation not permitted" even though user appservice is a member of both group pi and group appservice ... as confirmed by "info appservice"Mark Underwood
In case you are willing and able to switch to systemd to manage your application, take a look at this answer: stackoverflow.com/a/22121547/272180yglodt
YES! That appears to have worked just fine, yglodt. Thank you.Mark Underwood
If you'll repost that as an answer, I'll accept it. I still don't know whether that matters or not, just want to give you credit for solving my problem.Mark Underwood
I posted an answer adapted to your case.yglodt

1 Answers

1
votes

I would recommend to run and manage your application with systemd.

This makes it very easy to run the application under a specific user.

To do so, go on as follows:

First, create a service definition file /etc/systemd/system/myapp.service with this content:

[Unit]
Description=My App

[Service]
User=nobody
# The configuration file application.properties should be here:
WorkingDirectory=/home/appservice/myapp/files 
ExecStart=/usr/bin/java -Xmx256m -jar myapp.jar
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

Then, notify systemd of the new service file:

systemctl daemon-reload

and enable it, so it runs on boot:

systemctl enable myapp.service

At the end you can use the following commands to start/stop your new service:

systemctl start myapp
systemctl stop myapp