VirtualBox

source: vbox/trunk/src/VBox/Installer/linux/routines.sh@ 76046

Last change on this file since 76046 was 76046, checked in by vboxsync, 6 years ago

Linux installers: do not call daemon-restart too often.
bugref:3809: Linux installer maintenance
Some versions of systemd can crash if daemon-restart is called too often, so
only call it once per installation or uninstallation. Do some clean-up of
overly-generic shell script as well.

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 12.1 KB
Line 
1# Oracle VM VirtualBox
2# VirtualBox installer shell routines
3#
4
5#
6# Copyright (C) 2007-2017 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
17ro_LOG_FILE=""
18ro_X11_AUTOSTART="/etc/xdg/autostart"
19ro_KDE_AUTOSTART="/usr/share/autostart"
20
21## Aborts the script and prints an error message to stderr.
22#
23# syntax: abort message
24
25abort()
26{
27 echo 1>&2 "$1"
28 exit 1
29}
30
31## Creates an empty log file and remembers the name for future logging
32# operations
33create_log()
34{
35 ## The path of the file to create.
36 ro_LOG_FILE="$1"
37 if [ "$ro_LOG_FILE" = "" ]; then
38 abort "create_log called without an argument! Aborting..."
39 fi
40 # Create an empty file
41 echo > "$ro_LOG_FILE" 2> /dev/null
42 if [ ! -f "$ro_LOG_FILE" -o "`cat "$ro_LOG_FILE"`" != "" ]; then
43 abort "Error creating log file! Aborting..."
44 fi
45}
46
47## Writes text to standard error, as standard output is masked.
48#
49# Syntax: info text
50info()
51{
52 echo 1>&2 "$1"
53}
54
55## Copies standard input to standard error, as standard output is masked.
56#
57# Syntax: info text
58catinfo()
59{
60 cat 1>&2
61}
62
63## Writes text to the log file
64#
65# Syntax: log text
66log()
67{
68 if [ "$ro_LOG_FILE" = "" ]; then
69 abort "Error! Logging has not been set up yet! Aborting..."
70 fi
71 echo "$1" >> $ro_LOG_FILE
72 return 0
73}
74
75## Writes test to standard output and to the log file
76#
77# Syntax: infolog text
78infolog()
79{
80 info "$1"
81 log "$1"
82}
83
84## Checks whether a module is loaded with a given string in its name.
85#
86# syntax: module_loaded string
87module_loaded()
88{
89 if [ "$1" = "" ]; then
90 log "module_loaded called without an argument. Aborting..."
91 abort "Error in installer. Aborting..."
92 fi
93 lsmod | grep -q $1
94}
95
96## Abort if we are not running as root
97check_root()
98{
99 if [ `id -u` -ne 0 ]; then
100 abort "This program must be run with administrator privileges. Aborting"
101 fi
102}
103
104## Abort if dependencies are not found
105check_deps()
106{
107 for i in ${@}; do
108 type "${i}" >/dev/null 2>&1 ||
109 abort "${i} not found. Please install: ${*}; and try again."
110 done
111}
112
113## Abort if a copy of VirtualBox is already running
114check_running()
115{
116 VBOXSVC_PID=`pidof VBoxSVC 2> /dev/null`
117 if [ -n "$VBOXSVC_PID" ]; then
118 if [ -f /etc/init.d/vboxweb-service ]; then
119 kill -USR1 $VBOXSVC_PID
120 fi
121 sleep 1
122 if pidof VBoxSVC > /dev/null 2>&1; then
123 echo 1>&2 "A copy of VirtualBox is currently running. Please close it and try again."
124 abort "Please note that it can take up to ten seconds for VirtualBox to finish running."
125 fi
126 fi
127}
128
129## Creates a systemd wrapper in /lib for an LSB init script
130systemd_wrap_init_script()
131{
132 self="systemd_wrap_init_script"
133 ## The init script to be installed. The file may be copied or referenced.
134 script="$(readlink -f -- "${1}")"
135 ## Name for the service.
136 name="$2"
137 test -x "$script" && test ! "$name" = "" || \
138 { echo "$self: invalid arguments" >&2 && return 1; }
139 test -d /usr/lib/systemd/system && unit_path=/usr/lib/systemd/system
140 test -d /lib/systemd/system && unit_path=/lib/systemd/system
141 test -n "${unit_path}" || \
142 { echo "$self: systemd unit path not found" >&2 && return 1; }
143 conflicts=`sed -n 's/# *X-Conflicts-With: *\(.*\)/\1/p' "${script}" | sed 's/\$[a-z]*//'`
144 description=`sed -n 's/# *Short-Description: *\(.*\)/\1/p' "${script}"`
145 required=`sed -n 's/# *Required-Start: *\(.*\)/\1/p' "${script}" | sed 's/\$[a-z]*//'`
146 startbefore=`sed -n 's/# *X-Start-Before: *\(.*\)/\1/p' "${script}" | sed 's/\$[a-z]*//'`
147 runlevels=`sed -n 's/# *Default-Start: *\(.*\)/\1/p' "${script}"`
148 servicetype=`sed -n 's/# *X-Service-Type: *\(.*\)/\1/p' "${script}"`
149 test -z "${servicetype}" && servicetype="forking"
150 targets=`for i in ${runlevels}; do printf "runlevel${i}.target "; done`
151 before=`for i in ${startbefore}; do printf "${i}.service "; done`
152 after=`for i in ${required}; do printf "${i}.service "; done`
153 cat > "${unit_path}/${name}.service" << EOF
154[Unit]
155SourcePath=${script}
156Description=${description}
157Before=${targets}shutdown.target ${before}
158After=${after}
159Conflicts=shutdown.target ${conflicts}
160
161[Service]
162Type=${servicetype}
163Restart=no
164TimeoutSec=5min
165IgnoreSIGPIPE=no
166KillMode=process
167GuessMainPID=no
168RemainAfterExit=yes
169ExecStart=${script} start
170ExecStop=${script} stop
171
172[Install]
173WantedBy=multi-user.target
174EOF
175}
176
177use_systemd()
178{
179 test ! -f /sbin/init || test -L /sbin/init
180}
181
182## Installs a file containing a shell script as an init script. Call
183# finish_init_script_install when all scripts have been installed.
184install_init_script()
185{
186 self="install_init_script"
187 ## The init script to be installed. The file may be copied or referenced.
188 script="$1"
189 ## Name for the service.
190 name="$2"
191
192 test -x "${script}" && test ! "${name}" = "" ||
193 { echo "${self}: invalid arguments" >&2; return 1; }
194 # Do not unconditionally silence the following "ln".
195 test -L "/sbin/rc${name}" && rm "/sbin/rc${name}"
196 ln -s "${script}" "/sbin/rc${name}"
197 if test -x "`which systemctl 2>/dev/null`"; then
198 if use_systemd; then
199 { systemd_wrap_init_script "$script" "$name"; return; }
200 fi
201 fi
202 if test -d /etc/rc.d/init.d; then
203 cp "${script}" "/etc/rc.d/init.d/${name}" &&
204 chmod 755 "/etc/rc.d/init.d/${name}"
205 elif test -d /etc/init.d; then
206 cp "${script}" "/etc/init.d/${name}" &&
207 chmod 755 "/etc/init.d/${name}"
208 else
209 { echo "${self}: error: unknown init type" >&2; return 1; }
210 fi
211}
212
213## Remove the init script "name"
214remove_init_script()
215{
216 self="remove_init_script"
217 ## Name of the service to remove.
218 name="$1"
219
220 test -n "${name}" ||
221 { echo "$self: missing argument"; return 1; }
222 rm -f "/sbin/rc${name}"
223 rm -f /lib/systemd/system/"$name".service /usr/lib/systemd/system/"$name".service
224 rm -f "/etc/rc.d/init.d/$name"
225 rm -f "/etc/init.d/$name"
226}
227
228## Tell systemd services have been installed or removed. Should not be done
229# after each individual one, as systemd can crash if it is done too often
230# (reported by the OL team for OL 7.6, may not apply to other versions.)
231finish_init_script_install()
232{
233 if use_systemd; then
234 systemctl daemon-reexec
235 fi
236}
237
238## Did we install a systemd service?
239systemd_service_installed()
240{
241 ## Name of service to test.
242 name="${1}"
243
244 test -f /lib/systemd/system/"${name}".service ||
245 test -f /usr/lib/systemd/system/"${name}".service
246}
247
248## Perform an action on a service
249do_sysvinit_action()
250{
251 self="do_sysvinit_action"
252 ## Name of service to start.
253 name="${1}"
254 ## The action to perform, normally "start", "stop" or "status".
255 action="${2}"
256
257 test ! -z "${name}" && test ! -z "${action}" ||
258 { echo "${self}: missing argument" >&2; return 1; }
259 if systemd_service_installed "${name}"; then
260 systemctl -q ${action} "${name}"
261 elif test -x "/etc/rc.d/init.d/${name}"; then
262 "/etc/rc.d/init.d/${name}" "${action}" quiet
263 elif test -x "/etc/init.d/${name}"; then
264 "/etc/init.d/${name}" "${action}" quiet
265 fi
266}
267
268## Start a service
269start_init_script()
270{
271 do_sysvinit_action "${1}" start
272}
273
274## Stop the init script "name"
275stop_init_script()
276{
277 do_sysvinit_action "${1}" stop
278}
279
280## Extract chkconfig information from a sysvinit script.
281get_chkconfig_info()
282{
283 ## The script to extract the information from.
284 script="${1}"
285
286 set `sed -n 's/# *chkconfig: *\([0-9]*\) *\(.*\)/\1 \2/p' "${script}"`
287 ## Which runlevels should we start in?
288 runlevels="${1}"
289 ## How soon in the boot process will we start, from 00 (first) to 99
290 start_order="${2}"
291 ## How soon in the shutdown process will we stop, from 99 (first) to 00
292 stop_order="${3}"
293 test ! -z "${name}" || \
294 { echo "${self}: missing name" >&2; return 1; }
295 expr "${start_order}" + 0 > /dev/null 2>&1 && \
296 expr 0 \<= "${start_order}" > /dev/null 2>&1 && \
297 test `expr length "${start_order}"` -eq 2 > /dev/null 2>&1 || \
298 { echo "${self}: start sequence number must be between 00 and 99" >&2;
299 return 1; }
300 expr "${stop_order}" + 0 > /dev/null 2>&1 && \
301 expr 0 \<= "${stop_order}" > /dev/null 2>&1 && \
302 test `expr length "${stop_order}"` -eq 2 > /dev/null 2>&1 || \
303 { echo "${self}: stop sequence number must be between 00 and 99" >&2;
304 return 1; }
305}
306
307## Add a service to its default runlevels (annotated inside the script, see get_chkconfig_info).
308addrunlevel()
309{
310 self="addrunlevel"
311 ## Service name.
312 name="${1}"
313
314 test -n "${name}" || \
315 { echo "${self}: missing argument" >&2; return 1; }
316 systemd_service_installed "${name}" && \
317 { systemctl -q enable "${name}"; return; }
318 if test -x "/etc/rc.d/init.d/${name}"; then
319 init_d_path=/etc/rc.d
320 elif test -x "/etc/init.d/${name}"; then
321 init_d_path=/etc
322 else
323 { echo "${self}: error: unknown init type" >&2; return 1; }
324 fi
325 get_chkconfig_info "${init_d_path}/init.d/${name}" || return 1
326 # Redhat based sysvinit systems
327 if test -x "`which chkconfig 2>/dev/null`"; then
328 chkconfig --add "${name}"
329 # SUSE-based sysvinit systems
330 elif test -x "`which insserv 2>/dev/null`"; then
331 insserv "${name}"
332 # Debian/Ubuntu-based systems
333 elif test -x "`which update-rc.d 2>/dev/null`"; then
334 # Old Debians did not support dependencies
335 update-rc.d "${name}" defaults "${start_order}" "${stop_order}"
336 # Gentoo Linux
337 elif test -x "`which rc-update 2>/dev/null`"; then
338 rc-update add "${name}" default
339 # Generic sysvinit
340 elif test -n "${init_d_path}/rc0.d"
341 then
342 for locali in 0 1 2 3 4 5 6
343 do
344 target="${init_d_path}/rc${locali}.d/K${stop_order}${name}"
345 expr "${runlevels}" : ".*${locali}" >/dev/null && \
346 target="${init_d_path}/rc${locali}.d/S${start_order}${name}"
347 test -e "${init_d_path}/rc${locali}.d/"[KS][0-9]*"${name}" || \
348 ln -fs "${init_d_path}/init.d/${name}" "${target}"
349 done
350 else
351 { echo "${self}: error: unknown init type" >&2; return 1; }
352 fi
353}
354
355
356## Delete a service from a runlevel
357delrunlevel()
358{
359 self="delrunlevel"
360 ## Service name.
361 name="${1}"
362
363 test -n "${name}" ||
364 { echo "${self}: missing argument" >&2; return 1; }
365 systemctl -q disable "${name}" >/dev/null 2>&1
366 # Redhat-based systems
367 chkconfig --del "${name}" >/dev/null 2>&1
368 # SUSE-based sysvinit systems
369 insserv -r "${name}" >/dev/null 2>&1
370 # Debian/Ubuntu-based systems
371 update-rc.d -f "${name}" remove >/dev/null 2>&1
372 # Gentoo Linux
373 rc-update del "${name}" >/dev/null 2>&1
374 # Generic sysvinit
375 rm -f /etc/rc.d/rc?.d/[SK]??"${name}"
376 rm -f /etc/rc?.d/[SK]??"${name}"
377}
378
379
380terminate_proc() {
381 PROC_NAME="${1}"
382 SERVER_PID=`pidof $PROC_NAME 2> /dev/null`
383 if [ "$SERVER_PID" != "" ]; then
384 killall -TERM $PROC_NAME > /dev/null 2>&1
385 sleep 2
386 fi
387}
388
389
390maybe_run_python_bindings_installer() {
391 VBOX_INSTALL_PATH="${1}"
392
393 PYTHON=python
394 if [ "`python -c 'import sys
395if sys.version_info >= (2, 6):
396 print \"test\"' 2> /dev/null`" != "test" ]; then
397 echo 1>&2 "Python 2.6 or later not available, skipping bindings installation."
398 return 1
399 fi
400
401 echo 1>&2 "Python found: $PYTHON, installing bindings..."
402 # Pass install path via environment
403 export VBOX_INSTALL_PATH
404 $SHELL -c "cd $VBOX_INSTALL_PATH/sdk/installer && $PYTHON vboxapisetup.py install \
405 --record $CONFIG_DIR/python-$CONFIG_FILES"
406 cat $CONFIG_DIR/python-$CONFIG_FILES >> $CONFIG_DIR/$CONFIG_FILES
407 rm $CONFIG_DIR/python-$CONFIG_FILES
408 # remove files created during build
409 rm -rf $VBOX_INSTALL_PATH/sdk/installer/build
410
411 return 0
412}
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