VirtualBox

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

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

Installer/linux: added support for pre-requisite test and pre-start command to HeadlessXOrg service script.

  • 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 service.
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. For details, options and configuration see the usage() function
20# further down.
21#
22# I have tried to follow the best practices I could find for writing a Linux
23# service (and doing it in shell script) which should work well with
24# traditional and modern service systems using minimal init or service files.
25# In our case this boils down to:
26# * Start with a single command line, stop using one of ${EXIT_SIGNALS} below.
27# * Stopping with a signal can be done safely using the pid stored in the
28# pid-file and our (presumably unique) command name. For this reason we
29# only support running one instance of the service though.
30# * Start in the foreground. Systems without proper service control can take
31# care of the backgrounding in the init script.
32# * Clean up all sub-processes (X servers) ourselves when we are stopped
33# cleanly and don't provide any other way to clean them up automatically (in
34# case we are stopped uncleanly) as we don't know of a generic safe way to
35# do so, though some service management systems (i.e. systemd) can do so.
36# (A more thorough automatic clean-up would be possible if Xorg didn't
37# potentially have to be run as root, so that we could run all processes
38# using a service-specific user account and just terminate all processes
39# run by that user to clean up.)
40
41## Default configuration file name.
42# @note This is not very nice - /etc/default is actually Debian-specific.
43CONFIGURATION_FILE=/etc/default/virtualbox
44## The name of this script.
45SCRIPT_NAME="$0"
46## Command line we were called with.
47SCRIPT_COMMAND_LINE="$0 $@"
48## The service name. Should match the init script name.
49SERVICE_NAME="vboxheadlessxorg"
50## The descriptive service name.
51SERVICE_LONG_NAME="VBoxHeadless X Server service"
52## Signals and conditions which may be used to terminate the service.
53EXIT_SIGNALS="EXIT HUP INT QUIT ABRT TERM"
54## The default X server configuration directory.
55DEFAULT_CONFIGURATION_FOLDER="/etc/vbox/headlessxorg.conf.d"
56
57## Print usage information for the service script.
58## @todo Perhaps we should support some of the configuration file options from
59# the command line. Opinions welcome.
60## @todo Possibly extract this information for the user manual.
61usage() {
62 cat << EOF
63Usage:
64
65 $(basename "${SCRIPT_NAME}") [<options>]
66
67Start one or several X servers in the background for use with headless
68rendering. We only support X.Org Server at the moment. Starting the X servers
69is managed by dropping one or more files xorg.conf.<n> into a configuration
70directory (by default ${DEFAULT_CONFIGURATION_FOLDER} - this can be overridden
71in the configuration file (see below). We will attempt to start an X server
72process for each configuration file using display number <n>.
73
74Options:
75
76 -c|--conf-file) Specify an alternative locations for the configuration
77 file. The default location is \"${CONFIGURATION_FILE}\".
78
79 --help|--usage Print this text.
80
81The optional configuration file should contain a series of lines of the form
82"KEY=value". It will be read in as a command shell sub-script. Here is the
83current list of possible key settings with a short explanation.
84
85 HEADLESS_X_ORG_CONFIGURATION_FOLDER
86 The folder where the configuration files for the X servers are to be found.
87
88 HEADLESS_X_ORG_LOG_FOLDER
89 The folder where log files will be created.
90
91 HEADLESS_X_ORG_LOG_FILE
92 The main log file name.
93
94 HEADLESS_X_ORG_RUN_FOLDER
95 The folder to store run-time data in.
96
97 HEADLESS_X_ORG_CHECK_PREREQUISITES
98 Shell command to execute to check whether all dependencies for the X
99 servers are available - usually a test for a device node. This will be
100 repeated at regular intervals until it returns successfully, so a command
101 which can be executed internally be the shell (like "[") is preferable.
102
103 HEADLESS_X_ORG_SERVER_PRE_COMMAND
104 Command to execute once to perform any set-up needed before starting the
105 X servers, such as setting up the X server authentication.
106
107 HEADLESS_X_ORG_SERVER_COMMAND
108 The default X server start-up command, containing the variables "${screen}"
109 for the screen number, "${conf_file}" for the configuration file path and
110 ${log_file} for the log file. The variables must be quoted for expansion
111 at evaluation time, e.g.
112 HEADLESS_X_ORG_SERVER_COMMAND="Xorg :\${screen} [...] > \"\${log_file}\"
113
114 HEADLESS_X_ORG_SERVER_LOG_FILE_TEMPLATE
115 The default X server log file name, containing the variable "${screen}" for
116 the screen number. The variable must be quoted for expansion at evaluation
117 time, e.g.
118 HEADLESS_X_ORG_SERVER_LOG_FILE_TEMPLATE="Xorg.\${screen}.log"
119EOF
120}
121
122# Default configuration.
123HEADLESS_X_ORG_CONFIGURATION_FOLDER="${DEFAULT_CONFIGURATION_FOLDER}"
124HEADLESS_X_ORG_LOG_FOLDER="/var/log/${SERVICE_NAME}"
125HEADLESS_X_ORG_LOG_FILE="${SERVICE_NAME}.log"
126HEADLESS_X_ORG_RUN_FOLDER="/var/run/${SERVICE_NAME}"
127HEADLESS_X_ORG_CHECK_PREREQUISITES="[ -e /dev/dri/card0 ]"
128X_AUTH_FILE="${HEADLESS_X_ORG_RUN_FOLDER}/xauth"
129HEADLESS_X_ORG_SERVER_PRE_COMMAND="echo > \"${X_AUTH_FILE}\"; xauth -f \"${X_AUTH_FILE}\" add :0 . \"\$(dd if=/dev/urandom count=1 bs=16 2>/dev/null | od -An -x)\""
130HEADLESS_X_ORG_SERVER_COMMAND="Xorg :\${screen} -auth \"${HEADLESS_X_ORG_RUN_FOLDER}/xauth\" -config \"\${conf_file}\" -logverbose 0 -logfile /dev/null -verbose 7 > \"\${log_file}\" 2>&1"
131HEADLESS_X_ORG_SERVER_LOG_FILE_TEMPLATE="Xorg.\${screen}.log"
132
133## The function definition at the start of every non-trivial shell script!
134abort() {
135 ## $@, ... Error text to output to standard error in printf format.
136 printf "$@" >&2
137 exit 1
138}
139
140## Milder version of abort, when we can't continue because of a valid condition.
141abandon() {
142 ## $@, ... Text to output to standard error in printf format.
143 printf "$@" >&2
144 exit 0
145}
146
147abort_usage() {
148 usage >&2
149 abort "$@"
150}
151
152# Print a banner message
153banner() {
154 cat << EOF
155${VBOX_PRODUCT} VBoxHeadless X Server start-up service Version ${VBOX_VERSION_STRING}
156(C) 2005-${VBOX_C_YEAR} ${VBOX_VENDOR}
157All rights reserved.
158
159EOF
160}
161
162# Get the directory where the script is located.
163VBOX_FOLDER="$(dirname "${SCRIPT_NAME}")"
164VBOX_FOLDER=$(cd "${VBOX_FOLDER}" && pwd)
165[ -d "${VBOX_FOLDER}" ] ||
166 abort "Failed to change to directory ${VBOX_FOLDER}.\n"
167# And change to the root directory so we don't hold any other open.
168cd /
169
170[ -r "${VBOX_FOLDER}/scripts/generated.sh" ] ||
171 abort "${LOG_FILE}" "Failed to find installation information in ${VBOX_FOLDER}.\n"
172. "${VBOX_FOLDER}/scripts/generated.sh"
173
174# Parse our arguments.
175while [ "$#" -gt 0 ]; do
176 case $1 in
177 -c|--conf-file)
178 [ "$#" -gt 1 ] ||
179 {
180 banner
181 abort "%s requires at least one argument.\n" "$1"
182 }
183 CONFIGURATION_FILE="$2"
184 shift
185 ;;
186 --help|--usage)
187 banner
188 usage
189 exit 0
190 ;;
191 *)
192 banner
193 abort_usage "Unknown argument $1.\n"
194 ;;
195 esac
196 shift
197done
198
199[ -r "${CONFIGURATION_FILE}" ] && . "${CONFIGURATION_FILE}"
200
201# If something fails here we will catch it when we create the directory.
202[ -e "${HEADLESS_X_ORG_LOG_FOLDER}" ] &&
203 [ -d "${HEADLESS_X_ORG_LOG_FOLDER}" ] &&
204 rm -rf "${HEADLESS_X_ORG_LOG_FOLDER}.old" 2> /dev/null &&
205mv "${HEADLESS_X_ORG_LOG_FOLDER}" "${HEADLESS_X_ORG_LOG_FOLDER}.old" 2> /dev/null
206mkdir -p "${HEADLESS_X_ORG_LOG_FOLDER}" 2>/dev/null ||
207{
208 banner
209 abort "Failed to create log folder \"${HEADLESS_X_ORG_LOG_FOLDER}\".\n"
210}
211mkdir -p "${HEADLESS_X_ORG_RUN_FOLDER}" 2>/dev/null ||
212{
213 banner
214 abort "Failed to create run folder \"${HEADLESS_X_ORG_RUN_FOLDER}\".\n"
215}
216exec > "${HEADLESS_X_ORG_LOG_FOLDER}/${HEADLESS_X_ORG_LOG_FILE}" 2>&1
217
218banner
219
220# Wait for our dependencies to become available. The increasing delay is
221# probably not the cleverest way to do this.
222DELAY=1
223while ! eval ${HEADLESS_X_ORG_CHECK_PREREQUISITES}; do
224 sleep $((${DELAY} / 10 + 1))
225 DELAY=$((${DELAY} + 1))
226done
227
228# Do any pre-start setup.
229eval "${HEADLESS_X_ORG_SERVER_PRE_COMMAND}"
230
231X_SERVER_PIDS=""
232trap "kill \${X_SERVER_PIDS} 2>/dev/null" ${EXIT_SIGNALS}
233space="" # Hack to put spaces between the pids but not before or after.
234for conf_file in "${HEADLESS_X_ORG_CONFIGURATION_FOLDER}"/*; do
235 [ x"${conf_file}" = x"${HEADLESS_X_ORG_CONFIGURATION_FOLDER}/*" ] &&
236 ! [ -e "${conf_file}" ] &&
237 abort "No configuration files found.\n"
238 filename="$(basename "${conf_file}")"
239 screen="$(expr "${filename}" : "xorg\.conf\.\(.*\)")"
240 [ 0 -le "${screen}" ] 2>/dev/null ||
241 abort "Badly formed file name \"${conf_file}\".\n"
242 log_file="${HEADLESS_X_ORG_LOG_FOLDER}/$(eval echo "${HEADLESS_X_ORG_SERVER_LOG_FILE_TEMPLATE}")"
243 eval "${HEADLESS_X_ORG_SERVER_COMMAND}" "&"
244 X_SERVER_PIDS="${X_SERVER_PIDS}${space}$!"
245 space=" "
246done
247wait
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