VirtualBox

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

Last change on this file since 93674 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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

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