How to Run Sbt as Daemon

How to run sbt as daemon?

Looks like sbt requested input from your terminal. If it does not really need input (which is probably the case when you run program in background), you can run it like this:

sbt run </dev/null >output-file &

See this answer for details.

EDIT

Ok, now that was a puzzle. Short answer: run sbt as follows:

setsid nohup sbt run &

Rationale:

The reason why sbt stops is arrival of SIGTTOU signal. It is delivered to background process in several cases, which include modifying terminal configuration. This is our case because according to strace -f sbt run &, sbt does a lot of black magic under the hood like this:

[pid 16600] execve("/usr/bin/sh", ["sh", "-c", "stty -g < /dev/tty"], [/* 75 vars */] <unfinished ...>

To work this around, you can run sbt in a different session to detach it from current terminal, so that it won't open /dev/tty and mess with our terminal.

Running SBT as Daemon

We launch test/demo apps with SBT in init.d all the time:

#!/bin/sh
# test lift web app

case "$1" in
'start')
cd /home/demouser/wa/HTML5DemoLift231/HTML5demo/
sbt jetty run
;;
'stop')
cd /home/demouser/wa/HTML5DemoLift231/HTML5demo/
sbt jetty stop
;;
*)
echo "Usage: $0 { start | stop }"
;;
esac
exit 0

This just works - we have had no problems with it. It may be different with a non-web app though.

How to keep sbt running (as a daemon process) after executing a command

sbt "; <command>; console"

does the trick. Note the initial semicolon is required.

Is there a simple way to fork a server process in sbt before starting test against that server?

fork doesn't run task in parallel - it just makes sure that tests are run in a separate JVM which helps with things like shutdown webhooks or disconnecting from services that doesn't handle resource release properly (e.g. DB connection that never calls disconnect).

If you want to use the same sbt to start server AND run test against that instance (which sounds like easily breakable antipattern BTW) you can use somethings like:

  • reStart
  • it:test
  • reStop

However that would be tricky because reStart yields immediately so tests would start when the server setup started but not necessarily completed. Race condition, failing tests, or blocking all tests until server finishes starting.

This is why nobody does it. Much easier to handle solution is to:

  • start the server in test in some beforeAll method and make this method complete only after server is responding to queries
  • shutdown it in some afterAll method (or somehow handle both of these using something like cats.effect.Resource or similar)
  • depending on situation:
    • running tests sequentially to avoid starting two instances at the same time or
    • generating config for each test so that they could be run in parallel without clashing on ports allocations

Anything else is just a hack that is going to fail sooner rather than later.

Running sbt in docker as non-root user

I understand that all of the "RUN" commands in your Dockerfile are as a root user.

SBT downloading Scala: Check where it is downloading. SBT by default downloads dependencies on ~/.ivy2 (and/or ~/.m2). If you change user, your home also changes, so it will look for dependencies in /home/jenkins/.ivy2, then on .ivy2 (double-check on this), which do not have those dependencies downloaded already, so it tries to download them.

About the var/cache/apt/archives/lock, it is trying to install via SBT via apt with your jenkins user, when you need to be privileged user to use apt. Your app-user should not need to install anything (or anything that requires root access), but rather build an image with all required installs and then use it as a separate user. Also, if apt gives you headaches, you can just install via download into folder, something like:

RUN \
curl -fsL http://downloads.typesafe.com/scala/$SCALA_VERSION/scala-$SCALA_VERSION.tgz | tar xfz - -C /usr/local && \
ln -s /usr/local/scala-$SCALA_VERSION/bin/* /usr/local/bin/

PS: You may want to run your container always as jenkins user, in that case you can use USER jenkins after you finished installations and do any additional unprivileged operations there.

Sbt-native-packager cannot connect to Docker daemon

I finally solved it by installing Sbt instead of Docker. I also use Docker in Docker service from Gitlab now that basically helps me avoid the problem above.

image: docker:19.03.12

services:
- mysql:latest
- docker:19.03.12-dind

docker:image:
needs: ["test"]
stage: deploy
before_script:
- apk update
- apk --no-cache add openjdk11
- export PATH="/usr/local/sbt/bin:$PATH"
- apk update && apk add bash ca-certificates wget tar && mkdir -p "/usr/local/sbt" && wget -qO - --no-check-certificate "https://github.com/sbt/sbt/releases/download/v1.5.5/sbt-1.5.5.tgz" | tar xz -C /usr/local/sbt --strip-components=1 && sbt sbtVersion
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- sbt docker:publishLocal
- docker tag x:latest registry.gitlab.com/x/y:0.1-SNAPSHOT-$(date +%Y-%m-%d-%H-%M)
- docker push registry.gitlab.com/x/y/project-$(date +%Y-%m-%d-%H-%M)
only:
- master

running daemon in background in scala console

Figured it out thanks to @som-snytt's link to @michael.kebe's answer on this SO entry: How does the “scala.sys.process” from Scala 2.9 work?

val pb = Process("""program""").run

Does exactly what I wanted



Related Topics



Leave a reply



Submit