-
Notifications
You must be signed in to change notification settings - Fork 445
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sysvinit script for debian package #85
Changes from 2 commits
9d0fa60
c1a927f
3e51206
96a0043
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
sbt.version=0.12.4 | ||
sbt.version=0.13.0 | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
#! /bin/sh | ||
|
||
### BEGIN INIT INFO | ||
# Provides: ${{app_name}} | ||
# Required-Start: $syslog | ||
# Required-Stop: $syslog | ||
# Default-Start: 2 3 4 5 | ||
# Default-Stop: | ||
# Short-Description: ${{descr}} | ||
### END INIT INFO | ||
|
||
PIDFILE=/var/run/${{app_name}}.pid | ||
DAEMON_USER=${{daemon_user}} | ||
|
||
. /lib/init/vars.sh | ||
. /lib/lsb/init-functions | ||
|
||
get_java_cmd() { | ||
if [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then | ||
echo "$JAVA_HOME/bin/java" | ||
else | ||
echo "java" | ||
fi | ||
} | ||
|
||
JAVA_CMD=$(get_java_cmd) | ||
|
||
RUN_CMD=$JAVA_CMD -cp ${{app_classpath}} ${{app_main_class}} | ||
|
||
case "$1" in | ||
|
||
start) log_daemon_msg "Starting ${{app_name}}" | ||
|
||
start-stop-daemon --background --start --chuid $DAEMON_USER --make-pidfile --pidfile $PIDFILE --exec $RUN_CMD | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice. I'm glad to see this stuff baked in now. |
||
|
||
;; | ||
stop) log_daemon_msg "Stopping ${{app_name}}" | ||
|
||
start-stop-daemon --stop --pidfile $PIDFILE --chuid $DAEMON_USER | ||
|
||
RETVAL=$? | ||
[ $RETVAL -eq 0 ] && [ -e "$PIDFILE" ] && rm -f $PIDFILE | ||
exit 2 | ||
;; | ||
*) log_daemon_msg "Usage: /etc/init.d/${{app_name}} {start|stop}" | ||
exit 2 | ||
;; | ||
esac | ||
exit 0 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,6 +46,8 @@ object SbtNativePackager extends Plugin | |
genericMappingSettings ++ archetypes.JavaAppPackaging.settings | ||
def java_server: Seq[Setting[_]] = | ||
genericMappingSettings ++ archetypes.JavaServerAppPackaging.settings | ||
def java_server_sysvinit: Seq[Setting[_]] = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm.... I'm wondering if we should instead do this via a flag setting..... That may complicate things, but the combinatorial explosion of "sysvinit", "upstart" and whatever shows up for RedHat/Windows/MacOSX may be a bit large.... |
||
genericMappingSettings ++ archetypes.JavaServerAppSysVinitPackaging.settings | ||
} | ||
|
||
// TODO - Add a few targets that detect the current OS and build a package for that OS. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,16 +6,14 @@ package com.typesafe.sbt.packager.archetypes | |
* Makes use of the associated upstart-template, with a few hooks | ||
* | ||
*/ | ||
object JavaAppUpstartScript { | ||
object JavaAppUpstartScript extends JavaAppScript { | ||
|
||
private[this] def upstartTemplateSource: java.net.URL = getClass.getResource("upstart-template") | ||
protected def templateSource: java.net.URL = getClass.getResource("upstart-template") | ||
|
||
private[this] def postinstTemplateSource: java.net.URL = getClass.getResource("postinst-template") | ||
private[this] def preremTemplateSource: java.net.URL = getClass.getResource("prerem-template") | ||
/** | ||
* | ||
* @param author - | ||
* @param description - short description | ||
* @param descr - short description | ||
* @param execScript - name of the script in /usr/bin | ||
* @param chdir - execution path of the script | ||
* @param retries - on fail, how often should a restart be tried | ||
|
@@ -36,11 +34,53 @@ object JavaAppUpstartScript { | |
"retries" -> retries.toString, | ||
"retryTimeout" -> retryTimeout.toString) | ||
|
||
} | ||
|
||
object JavaAppSysVinitScript extends JavaAppScript { | ||
protected def templateSource: java.net.URL = getClass.getResource("sysvinit-template") | ||
|
||
|
||
/** | ||
* | ||
* @param author - | ||
* @param description - short description | ||
* @return Seq of key,replacement pairs | ||
*/ | ||
def makeReplacements( | ||
author: String, | ||
description: String, | ||
appDir: String, | ||
appName: String, | ||
appMainClass: String, | ||
appClasspath: String, | ||
daemonUser: String | ||
|
||
): Seq[(String, String)] = | ||
Seq( | ||
"author" -> author, | ||
"descr" -> description, | ||
"app_name" -> appName, | ||
"app_dir" -> appDir, | ||
"app_main_class" -> appMainClass, | ||
"app_classpath" -> appClasspath, | ||
"daemon_user" -> daemonUser | ||
) | ||
} | ||
|
||
|
||
trait JavaAppScript { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice re-use. |
||
|
||
protected def templateSource: java.net.URL | ||
|
||
protected def postinstTemplateSource: java.net.URL = getClass.getResource("postinst-template") | ||
protected def preremTemplateSource: java.net.URL = getClass.getResource("prerem-template") | ||
|
||
|
||
def generateScript(replacements: Seq[(String, String)]): String = | ||
TemplateWriter.generateScript(upstartTemplateSource, replacements) | ||
TemplateWriter.generateScript(templateSource, replacements) | ||
|
||
def generatePrerm(appName: String): String = | ||
TemplateWriter.generateScript(preremTemplateSource, Seq("app_name" -> appName)) | ||
def generatePostinst(appName: String): String = | ||
TemplateWriter.generateScript(postinstTemplateSource, Seq("app_name" -> appName)) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,7 @@ import com.typesafe.sbt.packager.linux.LinuxPackageMapping | |
* | ||
* **NOTE: EXPERIMENTAL** This currently only supports debian upstart scripts. | ||
*/ | ||
object JavaServerAppPackaging { | ||
object JavaServerAppPackaging extends JavaServerAppPackaging { | ||
|
||
def settings: Seq[Setting[_]] = | ||
JavaAppPackaging.settings ++ | ||
|
@@ -42,26 +42,79 @@ object JavaServerAppPackaging { | |
debianMakePrermScript <<= (normalizedName, target in Universal) map makeDebianPrermScript, | ||
debianMakePostinstScript <<= (normalizedName, target in Universal) map makeDebianPostinstScript) | ||
|
||
private[this] final def makeDebianPrermScript(name: String, tmpDir: File): Option[File] = { | ||
|
||
private def makeDebianUpstartScript(replacements: Seq[(String, String)], name: String, tmpDir: File): Option[File] = | ||
if (replacements.isEmpty) None | ||
else { | ||
val scriptBits = JavaAppUpstartScript.generateScript(replacements) | ||
val script = tmpDir / "tmp" / "bin" / (name + ".conf") | ||
IO.write(script, scriptBits) | ||
Some(script) | ||
} | ||
} | ||
|
||
|
||
object JavaServerAppSysVinitPackaging extends JavaServerAppPackaging { | ||
|
||
def settings: Seq[Setting[_]] = | ||
JavaAppPackaging.settings ++ debianSysVinitSettings | ||
|
||
def debianSysVinitSettings: Seq[Setting[_]] = { | ||
Seq( | ||
debianSysVinitScriptReplacements <<= (maintainer in Debian, packageSummary in Debian, daemonUser in Debian, | ||
normalizedName, name, sbt.Keys.version, defaultLinuxInstallLocation, sbt.Keys.mainClass in Compile, scriptClasspath) | ||
map { (author, descr, daemonUser, normalizedName, name, version, installLocation, mainClass, cp) => | ||
// TODO name-version is copied from UniversalPlugin. This should be consolidated into a setting (install location...) | ||
val appDir = installLocation + "/" + normalizedName | ||
val appClasspath = cp.map(appDir + "/lib/" + _).mkString(":") | ||
|
||
JavaAppSysVinitScript.makeReplacements( | ||
author = author, description = descr, | ||
appDir = appDir, | ||
appName = name, | ||
appClasspath = appClasspath, | ||
appMainClass = mainClass.get, | ||
daemonUser = daemonUser | ||
) | ||
}, | ||
debianMakeSysVinitScript <<= (debianSysVinitScriptReplacements, normalizedName, target in Universal) map makeDebianSysVinitScript, | ||
linuxPackageMappings in Debian <++= (debianMakeSysVinitScript, normalizedName) map { (script, name) => | ||
for { | ||
s <- script.toSeq | ||
} yield LinuxPackageMapping(Seq(s -> ("/etc/init.d/" + name))).withPerms("0755") | ||
}, | ||
// TODO - only make these if the upstart config exists... | ||
debianMakePrermScript <<= (normalizedName, target in Universal) map makeDebianPrermScript, | ||
debianMakePostinstScript <<= (normalizedName, target in Universal) map makeDebianPostinstScript) | ||
} | ||
|
||
|
||
private def makeDebianSysVinitScript(replacements: Seq[(String, String)], name: String, tmpDir: File): Option[File] = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are their differences between System V init scripts in rpm vs. debian that would not let us re-use this mechanism? |
||
if (replacements.isEmpty) None | ||
else { | ||
val scriptBits = JavaAppSysVinitScript.generateScript(replacements) | ||
val script = tmpDir / "tmp" / "bin" / (name + ".conf") | ||
IO.write(script, scriptBits) | ||
Some(script) | ||
} | ||
} | ||
|
||
|
||
trait JavaServerAppPackaging { | ||
|
||
def settings: Seq[Setting[_]] | ||
|
||
protected def makeDebianPrermScript(name: String, tmpDir: File): Option[File] = { | ||
val scriptBits = JavaAppUpstartScript.generatePrerm(name) | ||
val script = tmpDir / "tmp" / "bin" / "debian-prerm" | ||
IO.write(script, scriptBits) | ||
Some(script) | ||
} | ||
|
||
private[this] final def makeDebianPostinstScript(name: String, tmpDir: File): Option[File] = { | ||
protected def makeDebianPostinstScript(name: String, tmpDir: File): Option[File] = { | ||
val scriptBits = JavaAppUpstartScript.generatePostinst(name) | ||
val script = tmpDir / "tmp" / "bin" / "debian-postinst" | ||
IO.write(script, scriptBits) | ||
Some(script) | ||
} | ||
|
||
private[this] final def makeDebianUpstartScript(replacements: Seq[(String, String)], name: String, tmpDir: File): Option[File] = | ||
if (replacements.isEmpty) None | ||
else { | ||
val scriptBits = JavaAppUpstartScript.generateScript(replacements) | ||
val script = tmpDir / "tmp" / "bin" / (name + ".conf") | ||
IO.write(script, scriptBits) | ||
Some(script) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -57,6 +57,20 @@ trait DebianKeys { | |
| retries - on fail, how often should a restart be tried | ||
| retryTimeout - pause between retries | ||
""".stripMargin) | ||
|
||
// Debian sysVinit scripts | ||
val debianMakeSysVinitScript = TaskKey[Option[File]]("makeSysVinitScript", "Creates or discovers the sysVinit script used by this project") | ||
val debianSysVinitScriptReplacements = TaskKey[Seq[(String, String)]]("sysVinitScriptReplacements", | ||
"""|Replacements of template parameters used in the sysVinit script. | ||
| Default supported templates: | ||
| execScript - name of the script in /usr/bin | ||
| daemonUser - daemon user | ||
| author - author of this project | ||
| descr - short description | ||
| retries - on fail, how often should a restart be tried | ||
| retryTimeout - pause between retries | ||
""".stripMargin) | ||
|
||
} | ||
|
||
/** Keys used for Debian specific settings. */ | ||
|
@@ -77,5 +91,8 @@ object Keys extends DebianKeys { | |
def target = sbt.Keys.target | ||
def streams = sbt.Keys.streams | ||
|
||
//init script parameters | ||
def daemonUser = linux.Keys.daemonUser | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool. I think we can re-use this for the RPM. |
||
|
||
val debianPackageInstallSize = TaskKey[Long]("debian-installed-size") | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import NativePackagerKeys._ | ||
|
||
packageArchetype.java_server_sysvinit | ||
|
||
name := "debian-test" | ||
|
||
version := "0.1.0" | ||
|
||
maintainer := "Josh Suereth <[email protected]>" | ||
|
||
packageSummary := "Test debian package" | ||
|
||
packageDescription := """A fun package description of our software, | ||
with multiple lines.""" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % sys.props("project.version")) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Run the debian packaging. | ||
> debian:package-bin | ||
$ exists target/debian-test-0.1.0.deb | ||
|
||
$ exists target/debian-test-0.1.0/etc | ||
$ exists target/debian-test-0.1.0/etc/init.d/debian-test | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice! Love that you added tests :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't actually upgrade yet, as we still support 0.12 for at least another 6 months.