Skip to content

Instantly share code, notes, and snippets.

@DennisLfromGA
Last active July 17, 2020 17:27
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • 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
@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