VirtualBox

source: vbox/trunk/src/VBox/Installer/linux/VBoxHeadlessXOrg.sh@ 43687

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

Installer/linux: Headless X.Org starter script, now somewhat tested.

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 9.2 KB
Line 
1#!/bin/sh
2#
3# VirtualBox X Server auto-start script.
4#
5# Copyright (C) 2012 Oracle Corporation
6#
7# This file is part of VirtualBox Open Source Edition (OSE), as
8# available from http://www.virtualbox.org. This file is free software;
9# you can redistribute it and/or modify it under the terms of the GNU
10# General Public License (GPL) as published by the Free Software
11# Foundation, in version 2 as it comes in the "COPYING" file of the
12# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
13# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
14#
15
16PATH=$PATH:/bin:/sbin:/usr/sbin
17
18## Start one or several X servers in the background for use with headless
19# rendering. We only support X.Org Server at the moment. Starting the X
20# servers is managed by dropping one or more files xorg.conf.<n> into the
21# directory ${HEADLESS_X_ORG_CONFIGURATION_DIRECTORY} - the default value
22# below can be overridden in the configuration file. We will attempt to start
23# an X server process for each configuration file using display number <n>.
24# For usage and options see the usage() function below this comment block.
25#
26# I have tried to follow the best practices I could find for writing a Linux
27# daemon process (and doing it in shell script) which should work well with
28# traditional and modern service systems using minimal init or service files.
29# In our case this boils down to:
30# * Start with a single command line, stop using one of ${EXIT_SIGNALS} below.
31# * Stopping with a signal can be done safely using the pid stored in the
32# pid-file and our (presumably unique) command name. For this reason we only
33# support running one instance of the service though.
34# * Support starting in the foreground for systems with proper service control.
35# * Support backgrounding with a pid-file for other systems.
36# * Clean up all sub-processes (X servers) ourselves when we are stopped
37# cleanly and don't provide any other way to clean them up automatically (in
38# case we are stopped uncleanly) as we don't know of a generic safe way to
39# do so, though some service management systems (i.e. systemd) can do so.
40# (A more thorough automatic clean-up would be possible if Xorg didn't
41# potentially have to be run as root, so that we could run all processes
42# using a service-specific user account and just terminate all processes
43# run by that user to clean up.)
44# * For this reason, our pid-file only contains the pid of the master process.
45# * To simplify system service and start-up message handling, we write
46# Debian-conform progress information to standard output (what processes we
47# are starting, information if we do something slow) and errors to standard
48# error. This should allow us to write pretty generic init/startup scripts
49# for different distributions which produce more-or-less correct output for
50# the system they run on.
51
52## Print usage information for the service script.
53usage() {
54 cat << EOF
55Usage:
56
57 $(basename "${SCRIPT_NAME}") [<options>]
58
59Do any system-wide set-up required to properly run the copy of VirtualBox
60residing in the current directory. If no options are specified, everything
61except --no-udev-and --log-file is assumed.
62
63Options:
64
65 -d|--daemonize) Detach fron the terminal and continue running in the
66 background.
67
68 -l|--log-folder) Create log files in this folder.
69
70 -p|--pidfile <name> Specify the name of the file to save the pids of child
71 processes in. Pass in an empty string to disable
72 pid-file creation.
73
74 -q|--quiet) Do not produce unnecessary console output. We still
75 show a banner if the command line arguments are
76 invalid.
77
78 --quick) Intended for internal use. Skip certain checks and
79 actions at start-up and print the command line
80 arguments to standard output.
81
82 --help|--usage Print this text.
83EOF
84}
85
86## Configuration file name.
87# Don't use vbox.cfg as that is currently automatically created and deleted.
88# Don't use /etc/default/virtualbox as that is Debian policy only and not very
89# nice. Let's try to use this in future and phase out the other two.
90## @todo Should we be using /etc/virtualbox instead of /etc/vbox?
91CONFIGURATION_FILE=/etc/vbox/vbox.conf
92
93## The name of this script.
94SCRIPT_NAME="$0"
95## Command line we were called with.
96SCRIPT_COMMAND_LINE="$0 $@"
97## The service name. Should match the init script name.
98SERVICE_NAME="vboxheadlessxorg"
99## The descriptive service name.
100SERVICE_LONG_NAME="VBoxHeadless X Server service"
101## Timeout in seconds when shutting down the service.
102SERVICE_SHUTDOWN_TIMEOUT=5
103## Signals and conditions which may be used to terminate the service.
104EXIT_SIGNALS="EXIT HUP INT QUIT ABRT TERM"
105
106# Default settings values, override in the configuration file.
107## The directory where the configuration files for the X servers are dropped.
108HEADLESS_X_ORG_CONFIGURATION_DIRECTORY=/etc/vbox/headlessxorg.conf.d
109## The path to the pidfile for the service.
110HEADLESS_X_ORG_PID_FILE="/var/run/${SERVICE_NAME}.pid"
111## The default log folder
112HEADLESS_X_ORG_LOG_FOLDER="/var/log/${SERVICE_NAME}"
113
114## The function definition at the start of every non-trivial shell script!
115abort() {
116 stop 2>/dev/null
117 ## $@, ... Error text to output to standard error in printf format.
118 printf "$@" >&2
119 exit 1
120}
121
122## Milder version of abort, when we can't continue because of a valid condition.
123abandon() {
124 stop 2>/dev/null
125 ## $@, ... Text to output to standard error in printf format.
126 printf "$@" >&2
127 exit 0
128}
129
130banner() {
131 cat << EOF
132${VBOX_PRODUCT} VBoxHeadless X Server start-up service Version ${VBOX_VERSION_STRING}
133(C) 2005-${VBOX_C_YEAR} ${VBOX_VENDOR}
134All rights reserved.
135
136EOF
137[ -n "${QUICK}" ] &&
138 printf "Internal command line: ${SCRIPT_COMMAND_LINE}\n\n"
139}
140
141abort_usage() {
142 usage >&2
143 abort "$@"
144}
145
146# Change to the directory where the script is located.
147MY_DIR="$(dirname "${SCRIPT_NAME}")"
148MY_DIR=`cd "${MY_DIR}" && pwd`
149[ -d "${MY_DIR}" ] ||
150 abort "Failed to change to directory ${MY_DIR}.\n"
151
152# Get installation configuration
153[ -r /etc/vbox/vbox.cfg ] || abort "/etc/vbox/vbox.cfg not found.\n"
154. /etc/vbox/vbox.cfg
155
156[ -r scripts/generated.sh ] ||
157 abort "${LOG_FILE}" "Failed to find installation information in ${MY_DIR}.\n"
158. scripts/generated.sh
159
160[ -r /etc/vbox/vbox.conf ] && . /etc/vbox/vbox.conf
161
162# Parse our arguments.
163while [ "$#" -gt 0 ]; do
164 case $1 in
165 -d|--daemonize)
166 DAEMONIZE=true
167 ;;
168 -l|--log-folder)
169 [ "$#" -gt 1 ] ||
170 {
171 banner
172 abort "%s requires at least one argument.\n" "$1"
173 }
174 HEADLESS_X_ORG_LOG_FOLDER="$2"
175 shift
176 ;;
177 -p|--pidfile)
178 [ "$#" -gt 1 ] ||
179 {
180 banner
181 abort "%s requires at least one argument.\n" "$1"
182 }
183 HEADLESS_X_ORG_PID_FILE="$2"
184 shift
185 ;;
186 -q|--quiet)
187 QUIET=true
188 ;;
189 --quick)
190 QUICK=true
191 ;;
192 --help|--usage)
193 usage
194 exit 0
195 ;;
196 *)
197 {
198 banner
199 abort_usage "Unknown argument $1.\n"
200 }
201 ;;
202 esac
203 shift
204done
205
206[ -z "${QUIET}" ] && banner
207
208if [ -z "${QUICK}" ]; then
209 [ -f "${HEADLESS_X_ORG_PID_FILE}" ] &&
210 ps -p "$(cat "${HEADLESS_X_ORG_PID_FILE}")" -o comm |
211 grep -q "${SERVICE_NAME}" &&
212 abort "The service appears to be already running.\n"
213
214 PIDFILE_DIRECTORY="$(dirname "${HEADLESS_X_ORG_PID_FILE}")"
215 { ! [ -d "${PIDFILE_DIRECTORY}" ] || ! [ -w "${PIDFILE_DIRECTORY}" ]; } &&
216 abort "Can't write to pid-file directory \"${PIDFILE_DIRECTORY}\".\n"
217
218 # If something fails here we will catch it when we create the directory.
219 [ -e "${HEADLESS_X_ORG_LOG_FOLDER}" ] &&
220 [ -d "${HEADLESS_X_ORG_LOG_FOLDER}" ] &&
221 rm -rf "${HEADLESS_X_ORG_LOG_FOLDER}.old" 2> /dev/null &&
222 mv "${HEADLESS_X_ORG_LOG_FOLDER}" "${HEADLESS_X_ORG_LOG_FOLDER}.old" 2> /dev/null
223 mkdir -p "${HEADLESS_X_ORG_LOG_FOLDER}" 2>/dev/null ||
224 abort "Failed to create log folder \"${HEADLESS_X_ORG_LOG_FOLDER}\".\n"
225fi # -z "${QUICK}"
226
227# Double background from shell script, disconnecting all standard streams, to
228# daemonise. This may fail if someone has connected something to another file
229# descriptor. This is intended (see e.g. fghack in the daemontools package).
230if [ -n "${DAEMONIZE}" ]; then
231 ("${SCRIPT_NAME}" --quick -p "${HEADLESS_X_ORG_PID_FILE}" < /dev/null > "${HEADLESS_X_ORG_LOG_FOLDER}/${SERVICE_NAME}.log" 2>&1 &) &
232 ## @todo wait for the servers to start accepting connections before exiting.
233 exit 0
234fi
235
236X_SERVER_PIDS=""
237trap "kill \${X_SERVER_PIDS} 2>/dev/null; exit 0" ${EXIT_SIGNALS}
238space="" # Hack to put spaces between the pids but not before or after.
239for file in "${HEADLESS_X_ORG_CONFIGURATION_DIRECTORY}"/xorg.conf.*; do
240 filename="$(basename "${file}")"
241 expr "${filename}" : "xorg.conf.[0-9]*" > /dev/null ||
242 { stop; abort "Badly formed file name \"${file}\".\n"; }
243 screen="${filename##*.}"
244 Xorg ":${screen}" -config "${file}" -logverbose 0 -logfile /dev/null -verbose 7 > "${HEADLESS_X_ORG_LOG_FOLDER}/Xorg.${screen}.log" 2>&1 &
245 X_SERVER_PIDS="${X_SERVER_PIDS}${space}$!"
246 space=" "
247done
248[ -n "${HEADLESS_X_ORG_PID_FILE}" ] &&
249 echo "$$" > "${HEADLESS_X_ORG_PID_FILE}"
250wait
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