VirtualBox

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

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

Installer/linux: headless X.Org, trivial adjustments.

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