VirtualBox

Changeset 43688 in vbox for trunk/src/VBox/Installer/linux


Ignore:
Timestamp:
Oct 18, 2012 7:39:16 PM (13 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
81506
Message:

Installer/linux: rewrite of the headless X.Org start-up script and a unit test.

Location:
trunk/src/VBox/Installer/linux
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Installer/linux/VBoxHeadlessXOrg.sh

    r43634 r43688  
    11#!/bin/sh
    22#
    3 # VirtualBox X Server auto-start script.
     3# VirtualBox X Server auto-start service.
    44#
    55# Copyright (C) 2012 Oracle Corporation
     
    1717
    1818## 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.
     19# rendering.  For details, options and configuration see the usage() function
     20# further down.
    2521#
    2622# 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
     23# service (and doing it in shell script) which should work well with
    2824# traditional and modern service systems using minimal init or service files.
    2925# In our case this boils down to:
    3026#  * Start with a single command line, stop using one of ${EXIT_SIGNALS} below.
    3127#  * 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.
     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.
    3632#  * Clean up all sub-processes (X servers) ourselves when we are stopped
    3733#    cleanly and don't provide any other way to clean them up automatically (in
     
    4238#    using a service-specific user account and just terminate all processes
    4339#    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.
    53 usage() {
    54   cat << EOF
    55 Usage:
    56 
    57   $(basename "${SCRIPT_NAME}") [<options>]
    58 
    59 Do any system-wide set-up required to properly run the copy of VirtualBox
    60 residing in the current directory.  If no options are specified, everything
    61 except --no-udev-and --log-file is assumed.
    62 
    63 Options:
    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.
    83 EOF
    84 }
    85 
    86 ## Configuration file name.
     40
     41## Default configuration file name.
    8742# Don't use vbox.cfg as that is currently automatically created and deleted.
    8843# Don't use /etc/default/virtualbox as that is Debian policy only and not very
     
    9045## @todo Should we be using /etc/virtualbox instead of /etc/vbox?
    9146CONFIGURATION_FILE=/etc/vbox/vbox.conf
    92 
    9347## The name of this script.
    9448SCRIPT_NAME="$0"
     
    9953## The descriptive service name.
    10054SERVICE_LONG_NAME="VBoxHeadless X Server service"
    101 ## Timeout in seconds when shutting down the service.
    102 SERVICE_SHUTDOWN_TIMEOUT=5
    10355## Signals and conditions which may be used to terminate the service.
    10456EXIT_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.
    108 HEADLESS_X_ORG_CONFIGURATION_DIRECTORY=/etc/vbox/headlessxorg.conf.d
    109 ## The path to the pidfile for the service.
    110 HEADLESS_X_ORG_PID_FILE="/var/run/${SERVICE_NAME}.pid"
    111 ## The default log folder
     57## The default X server configuration directory.
     58DEFAULT_CONFIGURATION_FOLDER="/etc/vbox/headlessxorg.conf.d"
     59
     60## Print usage information for the service script.
     61## @todo Perhaps we should support some of the configuration file options from
     62#        the command line.  Opinions welcome.
     63## @todo Possibly extract this information for the user manual.
     64usage() {
     65  cat << EOF
     66Usage:
     67
     68  $(basename "${SCRIPT_NAME}") [<options>]
     69
     70Start one or several X servers in the background for use with headless
     71rendering.  We only support X.Org Server at the moment.  Starting the X servers
     72is managed by dropping one or more files xorg.conf.<n> into a configuration
     73directory (by default ${DEFAULT_CONFIGURATION_FOLDER} - this can be overridden
     74in the configuration file (see below).  We will attempt to start an X server
     75process for each configuration file using display number <n>.
     76
     77Options:
     78
     79  -c|--conf-file)        Specify an alternative locations for the configuration
     80                         file.  The default location is \"${CONFIGURATION_FILE}\".
     81
     82  --help|--usage         Print this text.
     83
     84The optional configuration file should contain a series of lines of the form
     85"KEY=value".  It will be read in as a command shell sub-script.  Here is the
     86current list of possible key settings with a short explanation.
     87
     88  HEADLESS_X_ORG_CONFIGURATION_FOLDER
     89    The folder where the configuration files for the X servers are to be found.
     90
     91  HEADLESS_X_ORG_LOG_FOLDER
     92    The default log folder.
     93
     94  HEADLESS_X_ORG_LOG_FILE
     95    The default log file.
     96
     97  HEADLESS_X_ORG_SERVER_COMMAND
     98    The default X server start-up command, containing the variables "${screen}"
     99    for the screen number, "${conf_file}" for the configuration file path and
     100    ${log_file} for the log file.  The variables must be quoted for expansion
     101    at evaluation time, e.g.
     102      HEADLESS_X_ORG_SERVER_COMMAND="Xorg :\${screen} [...] > \"\${log_file}\"
     103
     104  HEADLESS_X_ORG_SERVER_LOG_FILE_TEMPLATE
     105    The default X server log file name, containing the variable "${screen}" for
     106    the screen number.  The variable must be quoted for expansion at evaluation
     107    time, e.g.
     108      HEADLESS_X_ORG_SERVER_LOG_FILE_TEMPLATE="Xorg.\${screen}.log"
     109EOF
     110}
     111
     112# Default configuration.
     113HEADLESS_X_ORG_CONFIGURATION_FOLDER="${DEFAULT_CONFIGURATION_FOLDER}"
    112114HEADLESS_X_ORG_LOG_FOLDER="/var/log/${SERVICE_NAME}"
     115HEADLESS_X_ORG_LOG_FILE="${SERVICE_NAME}.log"
     116HEADLESS_X_ORG_SERVER_COMMAND="Xorg :\${screen} -config \"\${conf_file}\" -logverbose 0 -logfile /dev/null -verbose 7 > \"\${log_file}\" 2>&1"
     117HEADLESS_X_ORG_SERVER_LOG_FILE_TEMPLATE="Xorg.\${screen}.log"
    113118
    114119## The function definition at the start of every non-trivial shell script!
    115120abort() {
    116   stop 2>/dev/null
    117121  ## $@, ... Error text to output to standard error in printf format.
    118122  printf "$@" >&2
     
    122126## Milder version of abort, when we can't continue because of a valid condition.
    123127abandon() {
    124   stop 2>/dev/null
    125128  ## $@, ... Text to output to standard error in printf format.
    126129  printf "$@" >&2
     
    128131}
    129132
     133abort_usage() {
     134  usage >&2
     135  abort "$@"
     136}
     137
     138# Print a banner message
    130139banner() {
    131140  cat << EOF
     
    135144
    136145EOF
    137 [ -n "${QUICK}" ] &&
    138   printf "Internal command line: ${SCRIPT_COMMAND_LINE}\n\n"
    139 }
    140 
    141 abort_usage() {
    142   usage >&2
    143   abort "$@"
    144 }
    145 
    146 # Change to the directory where the script is located.
    147 MY_DIR="$(dirname "${SCRIPT_NAME}")"
    148 MY_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
     146}
     147
     148# Get the directory where the script is located.
     149VBOX_FOLDER="$(dirname "${SCRIPT_NAME}")"
     150VBOX_FOLDER=$(cd "${VBOX_FOLDER}" && pwd)
     151[ -d "${VBOX_FOLDER}" ] ||
     152  abort "Failed to change to directory ${VBOX_FOLDER}.\n"
     153# And change to the root directory so we don't hold any other open.
     154cd /
     155
     156[ -r "${VBOX_FOLDER}/scripts/generated.sh" ] ||
     157  abort "${LOG_FILE}" "Failed to find installation information in ${VBOX_FOLDER}.\n"
     158. "${VBOX_FOLDER}/scripts/generated.sh"
    161159
    162160# Parse our arguments.
    163161while [ "$#" -gt 0 ]; do
    164162  case $1 in
    165     -d|--daemonize)
    166       DAEMONIZE=true
    167       ;;
    168     -l|--log-folder)
     163    -c|--conf-file)
    169164      [ "$#" -gt 1 ] ||
    170         {
    171           banner
    172           abort "%s requires at least one argument.\n" "$1"
    173         }
    174       HEADLESS_X_ORG_LOG_FOLDER="$2"
     165      {
     166        banner
     167        abort "%s requires at least one argument.\n" "$1"
     168      }
     169      CONFIGURATION_FILE="$2"
    175170      shift
    176171      ;;
    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       ;;
    192172    --help|--usage)
     173      banner
    193174      usage
    194175      exit 0
    195176      ;;
    196177    *)
    197       {
    198         banner
    199         abort_usage "Unknown argument $1.\n"
    200       }
     178      banner
     179      abort_usage "Unknown argument $1.\n"
    201180      ;;
    202181  esac
     
    204183done
    205184
    206 [ -z "${QUIET}" ] && banner
    207 
    208 if [ -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"
    225 fi # -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).
    230 if [ -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
    234 fi
     185[ -r "${CONFIGURATION_FILE}" ] && . "${CONFIGURATION_FILE}"
     186
     187# If something fails here we will catch it when we create the directory.
     188[ -e "${HEADLESS_X_ORG_LOG_FOLDER}" ] &&
     189  [ -d "${HEADLESS_X_ORG_LOG_FOLDER}" ] &&
     190  rm -rf "${HEADLESS_X_ORG_LOG_FOLDER}.old" 2> /dev/null &&
     191mv "${HEADLESS_X_ORG_LOG_FOLDER}" "${HEADLESS_X_ORG_LOG_FOLDER}.old" 2> /dev/null
     192mkdir -p "${HEADLESS_X_ORG_LOG_FOLDER}" 2>/dev/null ||
     193{
     194  banner
     195  abort "Failed to create log folder \"${HEADLESS_X_ORG_LOG_FOLDER}\".\n"
     196}
     197exec > "${HEADLESS_X_ORG_LOG_FOLDER}/${HEADLESS_X_ORG_LOG_FILE}" 2>&1
     198
     199banner
    235200
    236201X_SERVER_PIDS=""
    237 trap "kill \${X_SERVER_PIDS} 2>/dev/null; exit 0" ${EXIT_SIGNALS}
     202trap "kill \${X_SERVER_PIDS} 2>/dev/null" ${EXIT_SIGNALS}
    238203space=""  # Hack to put spaces between the pids but not before or after.
    239 for 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 &
     204for conf_file in "${HEADLESS_X_ORG_CONFIGURATION_FOLDER}"/*; do
     205  [ x"${conf_file}" = x"${HEADLESS_X_ORG_CONFIGURATION_FOLDER}/*" ] &&
     206    ! [ -e "${conf_file}" ] &&
     207    abort "No configuration files found.\n"
     208  filename="$(basename "${conf_file}")"
     209  screen="$(expr "${filename}" : "xorg\.conf\.\(.*\)")"
     210  [ 0 -le "${screen}" ] 2>/dev/null ||
     211    abort "Badly formed file name \"${conf_file}\".\n"
     212  log_file="${HEADLESS_X_ORG_LOG_FOLDER}/$(eval echo "${HEADLESS_X_ORG_SERVER_LOG_FILE_TEMPLATE}")"
     213  eval "${HEADLESS_X_ORG_SERVER_COMMAND}" "&"
    245214  X_SERVER_PIDS="${X_SERVER_PIDS}${space}$!"
    246215  space=" "
    247216done
    248 [ -n "${HEADLESS_X_ORG_PID_FILE}" ] &&
    249   echo "$$" > "${HEADLESS_X_ORG_PID_FILE}"
    250217wait
  • trunk/src/VBox/Installer/linux/testcase/Makefile.kmk

    r41477 r43688  
    3939        $(QUIET)$(CHMOD) a+rx,u+w $@
    4040
     41INSTALLS += tstHeadlessXOrg
     42TESTING += tstHeadlessXOrg
     43tstHeadlessXOrg_INST    = $(INST_TESTCASE)
     44tstHeadlessXOrg_MODE    = a+rx,u+w
     45tstHeadlessXOrg_SOURCES = tstHeadlessXOrg.sh
     46
    4147include $(FILE_KBUILD_SUB_FOOTER)
Note: See TracChangeset for help on using the changeset viewer.

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