VirtualBox

source: vbox/trunk/src/VBox/Installer/linux/install_service/install_service.sh@ 44049

Last change on this file since 44049 was 44049, checked in by vboxsync, 12 years ago

Installer/linux: finish init script generator and add a couple of test cases.

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 8.3 KB
Line 
1#!/bin/sh
2
3#
4# Script to install services within a VirtualBox installation.
5#
6# Copyright (C) 2012 Oracle Corporation
7#
8# This file is part of VirtualBox Open Source Edition (OSE), as
9# available from http://www.virtualbox.org. This file is free software;
10# you can redistribute it and/or modify it under the terms of the GNU
11# General Public License (GPL) as published by the Free Software
12# Foundation, in version 2 as it comes in the "COPYING" file of the
13# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15
16# Clean up before we start.
17cr="
18"
19tab=" "
20IFS=" ${cr}${tab}"
21'unset' -f unalias
22'unalias' -a 2>/dev/null
23'unset' -f command
24PATH=/bin:/sbin:/usr/bin:/usr/sbin:$PATH
25
26## Script usage documentation.
27## @todo generate_service_file could be called to print its own documentation.
28usage() {
29 cat << EOF
30Usage:
31
32 `basename $0` --help|--usage|<options>
33
34Create a system service which runs a command. In order to make it possible to
35do this in a simple and portable manner, we place a number of requirements on
36the command to be run:
37 - That it can be started safely even if all its dependencies are not started
38 and will sleep if necessary until it can start work. Ideally it should start
39 accepting input as early as it can, but delay handling it if necessary.
40 - That it does not background to simplify service process management.
41 - That it can be safely shut down using SIGTERM.
42 - That if all running copies of the main process binary are stopped first the
43 service can be re-started and will do any necessary clean-up automatically.
44 - That any output which must not be lost go either to the system log or to the
45 service's private log.
46
47We currently support System V init only. This will probably soon be extended
48to BSD init, OpenRC, Pardus Comar and systemd, but probably not Upstart which
49currently requires modifying init files to disable a service. We also try to
50enable our service (if requested) in all init systems we find, as we do not know
51which one is in active use. We assume that this will not have any adverse
52effects.
53
54 --help|--usage
55 Print this help text and exit.
56
57Required options:
58
59 --command <command>
60 The absolute path of the executable file to be started by the service. No
61 form of quoting should be used here.
62
63 --description <description>
64 A short description of the service which can also be used in sentences
65 like "<description> failed to start", as a single parameter. ASCII
66 characters 0 to 31 and 127 should not be used.
67
68Other options:
69
70 --arguments <arguments>
71 The arguments to pass to the executable file when it is started, as a
72 single parameter. ASCII characters 0 to 31, "'" and 127 should be escaped
73 in C string-style and spaces inside words should be preceeded by a back
74 slash. Some systemd-style % sequences may be added at a future time.
75
76 --service-name <name>
77 Specify the name of the service. By default the base name without the
78 extension of the command binary is used. Only ASCII characters 33 to 126
79 should be used.
80
81 --enabled
82 Enable the service in normal user run-levels by default. If this option
83 is not used the service will be disabled by default. If a version of the
84 service was already installed this option (or its absence) will be
85 ignored unless the "--force" option is also specified.
86
87 --force
88 Respect the presence or absence of the "--enabled" flag even if a previous
89 version of the service was already installed with a different enablement
90 state.
91
92 --prefix <prefix>
93 Treat all paths as relative to <prefix> rather than /etc.
94EOF
95}
96
97## The function definition at the start of every non-trivial shell script!
98abort() {
99 ## $1 Error text to output to standard error.
100 cat >&2 << EOF
101$1
102EOF
103 exit 1
104}
105
106enabled=""
107force=""
108PREFIX="/etc/"
109ARGUMENTS=""
110SERVICE_NAME=""
111
112# Process arguments.
113## @todo Pass more through unmodified to generate_service_file to reduce
114# duplication. Or then again, maybe the hassle of perserving the
115# positional parameters is not worth it.
116while test x"${#}" != "x0"; do
117 case "${1}" in
118 "--help|--usage")
119 usage
120 exit 0;;
121 "--enabled")
122 enabled=true
123 shift;;
124 "--force")
125 force=true
126 shift;;
127 "--prefix")
128 test -z "${2}" && abort "${1}: missing argument."
129 PREFIX="${2}"
130 shift 2;;
131 "--command")
132 test -z "${2}" && abort "${1}: missing argument."
133 COMMAND="${2}"
134 shift 2;;
135 "--arguments")
136 test -z "${2}" && abort "${1}: missing argument."
137 ARGUMENTS="${2}"
138 shift 2;;
139 "--description")
140 test -z "${2}" && abort "${1}: missing argument."
141 DESCRIPTION="${2}"
142 shift 2;;
143 "--service-name")
144 test -z "${2}" && abort "${1}: missing argument."
145 SERVICE_NAME="${2}"
146 shift 2;;
147 *)
148 abort "Unknown option ${1}.";;
149 esac
150done
151
152# Check required options and set default values for others.
153test -z "${COMMAND}" &&
154 abort "Please supply a start command."
155test -f "${COMMAND}" && test -x "${COMMAND}" ||
156 abort "The start command must be an executable file."
157case "${COMMAND}" in
158 /*) ;;
159 *) abort "The start command must have an absolute path." ;;
160esac
161test -z "${DESCRIPTION}" &&
162 abort "Please supply a service description."
163# Get the service name from the command path if not explicitly
164# supplied.
165test -z "${SERVICE_NAME}" &&
166 SERVICE_NAME="`expr "${COMMAND}" : '.*/\(.*\)\..*'`"
167test -z "${SERVICE_NAME}" &&
168 SERVICE_NAME="`expr "${COMMAND}" : '.*/\(.*\)'`"
169
170# Get the folder we are running from, as we need other files there.
171script_folder="`dirname "$0"`"
172script_folder="`cd "${script_folder}" && pwd`"
173test -d "${script_folder}" ||
174 abort "Failed to find the folder this command is running from."
175
176# Keep track of whether we found at least one initialisation system.
177found_init=""
178# And whether we found a previous service script/file.
179update=""
180
181# Find the best System V/BSD init path if any is present.
182for path in "${PREFIX}/init.d/rc.d" "${PREFIX}/init.d/" "${PREFIX}/rc.d/init.d" "${PREFIX}/rc.d"; do
183 if test -d "${path}"; then
184 found_init="true"
185 test -f "${path}/${SERVICE_NAME}" && update="true"
186 "${script_folder}/generate_service_file" --format shell --command "${COMMAND}" --arguments "${ARGUMENTS}" --description "${DESCRIPTION}" --service-name "${SERVICE_NAME}" < "${script_folder}/init_template.sh" > "${path}/${SERVICE_NAME}"
187 chmod a+x "${path}/${SERVICE_NAME}"
188 # Attempt to install using both system V symlinks and OpenRC, assuming
189 # that both will not be in operation simultaneously (but may be
190 # switchable). BSD init expects the user to enable services explicitly.
191 if test -z "${update}" || test -n "${force}"; then
192 # Various known combinations of sysvinit rc directories.
193 for i in ${PREFIX}/rc*.d/[KS]??"${SERVICE_NAME}" ${PREFIX}/rc.d/rc*.d/[KS]??"${SERVICE_NAME}"; do
194 rm -f "$i"
195 done
196 # And OpenRC.
197 type rc-update > /dev/null 2>&1 &&
198 rc-update del "${1}" > /dev/null 2>&1
199 # Various known combinations of sysvinit rc directories.
200 if test -n "${enabled}"; then
201 for i in rc0.d rc1.d rc6.d rc.d/rc0.d rc.d/rc1.d rc.d/rc6.d; do
202 if test -d "${PREFIX}/${i}"; then
203 # Paranoia test first.
204 test -d "${PREFIX}/${i}/K80${SERVICE_NAME}" ||
205 ln -sf "${path}/${SERVICE_NAME}" "${PREFIX}/${i}/K80${SERVICE_NAME}"
206 fi
207 done
208 for i in rc3.d rc4.d rc5.d rc.d/rc3.d rc.d/rc4.d rc.d/rc5.d; do
209 if test -d "${PREFIX}/${i}"; then
210 # Paranoia test first.
211 test -d "${PREFIX}/${i}/S20${SERVICE_NAME}" ||
212 ln -sf "${path}/${SERVICE_NAME}" "${PREFIX}/${i}/S20${SERVICE_NAME}"
213 fi
214 done
215 # And OpenRC.
216 type rc-update > /dev/null 2>&1 &&
217 rc-update add "${1}" default > /dev/null 2>&1
218 fi
219 fi
220 break
221 fi
222done
223
224test -z "${found_init}" &&
225 abort "No supported initialisation system found."
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette