Skip to content

Instantly share code, notes, and snippets.

@DennisLfromGA
Last active July 17, 2020 17:27
Show Gist options
  • Save DennisLfromGA/6443733 to your computer and use it in GitHub Desktop.
Save DennisLfromGA/6443733 to your computer and use it in GitHub Desktop.
A ChromeOS upstart script to kick-off a crouton chroot desktop environment.
# Copyright (c) 2016 The crouton Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
## Filename: /etc/init/crouton.conf
## NOTE: 'rootfs' verification needs to be removed.
## crouton chroot - Start session
##
## This will start a (crouton) chroot Desktop Environment session
description "Crouton Chroot Session daemon"
author "github/DennisLfromGA"
## Choose when the crouton chroot will be started - 4 choices below -
## NOTE: use only 1, prepend the others with the remark character: #
#start on starting ui # 1st - starts when the user interface begins
# + only 1 chroot will run in this mode
# + must use XMETHOD: 'xorg'
#start on started ui # 2nd - starts when the user interface appears
# + only 1 chroot will run in this mode
# + must use XMETHOD: 'xorg'
#start on login-prompt-visible # 3rd - starts when the login screen appears
# + only 1 chroot will run in this mode
# + must use XMETHOD: 'xorg'
start on start-user-session # 4th - starts when the user logs in - DEFAULT
# + multiple chroots could run in this mode
# + can use either XMETHOD: 'xiwi' or 'xorg'
# + ensures user ~/Downloads is available
stop on stopping ui or starting halt or starting reboot
############################################################################
## NOTE: This job can be controlled externally by placing the file ##
#+ 'crouton.init' in the User's Downloads folder on a per User ##
#+ basis or in the chroots parent folder per system with the ##
#+ following six optional variables set: ##
#+ 1) DELAY 2) CHROOT 3) START_DE 4) CHROOT_APP 5) XMETHOD 6) RUN_STATE ##
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
#+ [ the 'env ' prefix must be omitted in the control file ] ##
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
## Start of control file variables ##
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
env DELAY=10 # delay desired number of seconds before starting ##
env CHROOT=xenial # enter desired chroot to start ##
env START_DE=startxfce4 # enter desired Desktop Envirnoment to use ##
env CHROOT_APP=none # enter desired chroot application to run ##
env XMETHOD=default # enter temporary X-Window Envirnoment to use ##
env RUN_STATE=y # change to 'n' to disable running $CHROOT ##
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
## End of control file variables ##
############################################################################
##########################################################################
## System control parameters ##
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
env DEBUG=on # change to 'on' for DEBUGGING output ##
env MASTER_SW=on # change to 'off' to override running any $CHROOT ##
env MULTIPLES=on # change to 'off' to allow running only 1 $CHROOT ##
##########################################################################
script
PID="$$"
touch /tmp/$UPSTART_JOB-$PID.log
## For output, use 'grep $PID /var/log/messages'
LOGGER="logger -p local3.info -t $UPSTART_JOB($PID)"
trap "$LOGGER '### Exiting...'" EXIT
$LOGGER "###############"
$LOGGER "### Starting..."
if [ "$DEBUG" = 'on' ]; then
exec >> /tmp/$UPSTART_JOB-$PID.log 2>&1
set -x
$LOGGER "*** DEBUGGING turned ON."
$LOGGER "*** See '/tmp/$UPSTART_JOB-$PID.log' for output."
else
$LOGGER "*** DEBUGGING is OFF."
fi
if [ "$MASTER_SW" = "off" ]; then
## No chroots will run even if allowed by external control file(s).
$LOGGER "!!! The MASTER_SW has been turned OFF"
$LOGGER "No CHROOTS will run - period. Exiting."
$LOGGER "###############"
$LOGGER "### Ending....."
$LOGGER "###############"
exit 255
fi
MULTS="`pgrep -l crouton|head -n 1`"
if [ "$MULTIPLES" = "off" ]; then
## Multiple chroots cannot be run when more than one user is logged in.
if [ -n "$MULTS" ]; then
$LOGGER "!!! MULTIPLE CHROOTS has been turned OFF"
$LOGGER "No more CHROOTS will be run now. Exiting."
$LOGGER "###############"
$LOGGER "### Ending....."
$LOGGER "###############"
exit 255
fi
elif [ -n "$MULTS" ]; then
$LOGGER "*** MULTIPLE CHROOTS is turned ON"
$LOGGER "Now running an additional CHROOT."
$LOGGER "###############"
fi
$LOGGER "##- Main checks started."
if [ -d /var/crouton/chroots ]; then
## Uses the @drinkcat 'separate_partition' branch - as DEFAULT
CROUTON_BIN=/var/crouton/bin
CROUTON_CHROOTS=/var/crouton/chroots
# if [ ! -x $CROUTON_BIN ]; then
mount -i -o remount,exec /var
$LOGGER "*** '/var' directory is being mounted as executable."
# else
# $LOGGER "*** '$CROUTON_BIN' directory is already mounted as executable."
# fi
$LOGGER "###############"
elif [ -d /usr/local/chroots ]; then
## Uses the @dnschneid 'master' branch
CROUTON_BIN=/usr/local/bin
CROUTON_CHROOTS=/usr/local/chroots
$LOGGER "###############"
else
## Nothing found...
$LOGGER "*** Crouton 'chroots' directory is missing. Aborting!"
$LOGGER "###############"
exit 1
fi
if [ ! -d $CROUTON_BIN ]; then
$LOGGER "*** Crouton 'bin' directory is missing. Aborting!"
$LOGGER "###############"
exit 1
fi
$LOGGER "*** Crouton 'bin' directory is $CROUTON_BIN"
$LOGGER "*** Crouton 'chroots' directory is $CROUTON_CHROOTS"
$LOGGER "##- Check for external control."
USER_DOWNLOADS="/home/chronos/user/Downloads"
DOWNLOADS_INIT="$USER_DOWNLOADS/${UPSTART_JOB}.init"
CHROOTS_PARENT=`dirname $CROUTON_CHROOTS`
CROUTON_INIT="$CHROOTS_PARENT/${UPSTART_JOB}.init"
if [ -r $DOWNLOADS_INIT ]; then INIT_FILE="$DOWNLOADS_INIT"
elif [ -r $CROUTON_INIT ]; then INIT_FILE="$CROUTON_INIT"; fi
if [ -r $INIT_FILE ] && [ -s $INIT_FILE ]; then
$LOGGER "*** External control enabled via '$INIT_FILE' file."
## Pull in variables from external control file
Delay="` awk -F= '/^DELAY=/ {print $2; exit}' "$INIT_FILE"`"
Chroot="` awk -F= '/^CHROOT=/ {print $2; exit}' "$INIT_FILE"`"
Start_DE="` awk -F= '/^START_DE=/ {print $2; exit}' "$INIT_FILE"`"
Chroot_App="` awk -F= '/^CHROOT_APP=/ {print $2; exit}' "$INIT_FILE"`"
XMethod="` awk -F= '/^XMETHOD=/ {print $2; exit}' "$INIT_FILE"`"
Run_state="` awk -F= '/^RUN_STATE=/ {print $2; exit}' "$INIT_FILE"`"
if [ -n "$Delay" -a "$Delay" != "$DELAY" ]; then
$LOGGER "##* DELAY changed from: '$DELAY' to '$Delay'."
DELAY="$Delay"
fi
if [ -n "$Chroot" -a "$Chroot" != "$CHROOT" ]; then
$LOGGER "##* CHROOT changed from: '$CHROOT' to '$Chroot'."
CHROOT="$Chroot"
fi
if [ -n "$Start_DE" -a "$Start_DE" != "$START_DE" ]; then
$LOGGER "##* START_DE changed from: '$START_DE' to '$Start_DE'."
START_DE="$Start_DE"
fi
if [ -n "$Chroot_App" -a "$Chroot_App" != "$CHROOT_APP" ]; then
$LOGGER "##* CHROOT_APP: '$Chroot_App' will be executed."
CHROOT_APP="$Chroot_App"
else
CHROOT_APP=
fi
if [ -n "$XMethod" -a "$XMethod" != "$XMETHOD" ]; then
$LOGGER "##* XMETHOD changed from: '$XMETHOD' to '$XMethod'."
XMETHOD=$XMethod
elif [ "$XMETHOD" != "default" ]; then
$LOGGER "##* XMETHOD changed from: 'default' to '$XMETHOD'."
else
$LOGGER "##* XMETHOD unchanged - set to '$XMETHOD'."
fi
if [ -n "$Run_state" -a "$Run_state" != "$RUN_STATE" ]; then
$LOGGER "##* RUN_STATE changed from: '$RUN_STATE' to '$Run_state'."
RUN_STATE="$Run_state"
fi
else
$LOGGER "### NO external control file found, using internal defaults."
fi
$LOGGER "##- Secondary checks started."
if [ ! -d $CROUTON_CHROOTS/$CHROOT ]; then
$LOGGER "*** Crouton '$CHROOT' directory is missing. Aborting!"
$LOGGER "###############"
exit 1
elif [ ! -s $CROUTON_BIN/$START_DE -o ! -x $CROUTON_BIN/$START_DE ]; then
$LOGGER "*** Crouton '$START_DE' script is missing or not executable. Aborting!"
$LOGGER "###############"
exit 1
fi
case $XMETHOD in
xorg|xiwi*)
XMARG="-X $XMETHOD"
;;
default)
XMARG=
;;
*)
XMARG=
$LOGGER "##* XMETHOD: '$XMETHOD' is invalid so not set."
;;
esac
if [ "$RUN_STATE" = "n" -o "$MASTER_SW" = off ]; then
$LOGGER "*** The RUN_STATE for chroot '$CHROOT' is DISABLED. Exiting."
$LOGGER "###############"
exit 0
fi
$LOGGER "##- Starting main process in $DELAY seconds."
sleep $DELAY
$LOGGER "##$ $CROUTON_BIN/$START_DE -c $CROUTON_CHROOTS -n $CHROOT $XMARG $CHROOT_APP"
eval sudo $CROUTON_BIN/$START_DE -c $CROUTON_CHROOTS -n "$CHROOT" $XMARG "$CHROOT_APP"
$LOGGER "##- Completed: status $?"
$LOGGER "### Ending....."
$LOGGER "###############"
if [ "$DEBUG" = "y" ]; then
set +x
fi
end script
@DennisLfromGA
Copy link
Author

NOTE: I also tried using the file 'rc.local' containing 'sleep 60 && exec /usr/local/bin/startgnome -n raring -b' but that didn't work either :(

@dnschneid
Copy link

L29, try this:
exec /bin/sh -e "$LOCAL_BIN/$START_DE" -n "$CHROOT" -b || logger -t "$UPSTART_JOB" "$CHROOT-$START_DE start: status $?"

@DennisLfromGA
Copy link
Author

Hurray! It Works finally.

If anyone else decides to use this please note that -

  1. It requires the REMOVAL of rootfs verification on the active kernel partition.
    2) This version is using @drinkcat's 'separate_partition' branch which uses '/var/crouton' instead of '/usr/local' as the parent location for your 'bin' & 'chroots' folders.
  2. So... edit the lines prefixed with 'env ...' and make them your own ;-)

@dnschneid
Copy link

Don't you need to set XAUTHORITY in there?

@dnschneid
Copy link

Also, you may want to get rid of the || true and the set +x at the end...

@DennisLfromGA
Copy link
Author

Fixes & (hopefully) improvements:

  • made changes to handle both the 'master' and 'separate_partition' branch.
  • added some option fors DELAY, DEBUG, and start on ... possibilities.

@DennisLfromGA
Copy link
Author

Added $XAUTHORITY - duh ;(

@DennisLfromGA
Copy link
Author

enable disable

@DennisLfromGA
Copy link
Author

Improved & tweaked:

  • Renamed to 'crouton.conf' for simplification
  • Added comments & options to start at different boot / login states
  • Added option to use an external control file to define DELAY, CHROOT, START_DE, and RUN_STATE
  • The external control file name should track the UPSTART_JOB name with an '.init' suffix (I.E.) crouton.init

Some of the various boot / login states are listed below, the 4th option is the default:

#start on starting ui          # 1st - starts when the user interface begins
#start on started ui           # 2nd - starts when the user interface appears
#start on login-prompt-visible # 3rd - starts when the login screen appears
 start on start-user-session   # 4th - starts when the user logs in - DEFAULT
                               #     + ensures user ~/Downloads is available

A typical 'crouton.init' file, placed in the chroot's parent directory, is as follows:

##############################################################
## Place a '#' in the 1st column before the variable if you ##
#+ don't want to change it from the crouton.conf defaults.  ##
##############################################################

## change to desired number of seconds before starting
#DELAY=5
DELAY=30

## change to desired chroot to use
#CHROOT=elementary
CHROOT=raring
#CHROOT=trusty

## change to desired Desktop Envirnoment to use
#START_DE=startgnome
START_DE=startkde
#START_DE=startxfce4

## change to 'n' to disable running crouton.conf
#RUN_STATE=n

@dnschneid
Copy link

So fancy!

@DennisLfromGA
Copy link
Author

For mounting the CROUTON partition auto-magically at startup (made possible via @drinkcat's crouton/separate_partition branch), see mnt-crouton.conf.

@technotion
Copy link

thank you both for your work on this project! i am still trying to grasp where I am creating these files. I simply need the DE of linux to come up at startup. No intervention. eg. If power goes out, then the Chromebox should simply run as Linux. Some detailed steps would be greatly appreciated. Thank you!

@DennisLfromGA
Copy link
Author

@technotion,

ℹ️ Autostart crouton chroot at ChromeOS startup

You first need to remove rootfs verification and make the rootfs read-writable, check out this script 'rw-rootfs' for that. I've read that this supposedly 'breaks' updates but I've been doing this literally for years and I still get each and every update.

Then you have to place one or possibly two custom .conf scripts in the /etc/init folder, the first script 'mnt-crouton.conf is only needed if you are using @drinkcat's 'separate-partition branch' and the second script, 'crouton.conf' is the one that will kick-off a chroot without opening a shell.

~~Lastly, you can optionally place a file named 'crouton.init' in your ~/Downloads folder or the chroot parent folder for external control, see one of the above comments for the format of this file.~~

@DennisLfromGA
Copy link
Author

This latest version allows the script to be controlled externally by -

  1. placing the file '${UPSTART_JOB}.init' ( usually 'crouton.init' ) in the User's Downloads folder on a per User basis or
  2. in the chroots parent folder per system

It also now runs in the foreground so it's an active process that can be accessed via 'initctl'.

@DennisLfromGA
Copy link
Author

Added additional System control parameters MASTER_SW and MULTIPLES.
Also added a bit more explanation and rules for starting the chroot(s).

@DennisLfromGA
Copy link
Author

Added XMETHOD option to allow starting the chroot using xorg, xephyr, or xiwi if installed.

@Timvrakas
Copy link

I believe the bin folder location is wrong for separate_partition. Also the default START_DE needs to be startxfce, not just xfce.
I don't know If you can "pull" a gist, but my fork has the changes.

@DennisLfromGA
Copy link
Author

Updated release to use 'xenial'.

@DennisLfromGA
Copy link
Author

Updated to mount /var as exec if needed.

@DennisLfromGA
Copy link
Author

Updated & improved mounting /var logic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment