#!/bin/bash -eu if [[ $EUID -ne 0 ]] then echo "STOP: Run sudo -i." exit 1 fi if [ "$(. /etc/os-release && echo "${VERSION_ID:-}")" = "9" ] then echo "STOP: Stretch-based install is no longer supported. Please flash the latest prebuilt." exit 1 fi if [ "${FLOCKED:-}" != "$0" ] then if FLOCKED="$0" flock -en -E 99 "$0" "$0" "$@" || case "$?" in 99) echo already running exit 99 ;; *) exit $? ;; esac then # success exit 0 fi fi function setup_progress () { local setup_logfile=/teslausb/teslausb-headless-setup.log if [ -w $setup_logfile ] then echo "$( date ) : $*" >> "$setup_logfile" fi echo "$@" } function curlwrapper () { setup_progress "curl $*" > /dev/null local attempts=0 while ! curl -s -S --stderr /tmp/curl.err --fail "$@" do attempts=$((attempts + 1)) if [ "$attempts" -ge 20 ] then setup_progress "giving up after 20 tries" if [ -e /tmp/curl.err ] then setup_progress "$(cat /tmp/curl.err)" else setup_progress '(no reason given)' fi exit 1 fi setup_progress "'curl $*' failed, retrying" > /dev/null sntp -S time.google.com || true sleep 3 done } function copy_script () { local remote_path="$1" local name="${1/*\/}" local local_path="$2" if [ -z ${SOURCE_DIR:+x} ] then if declare -F download_sources &> /dev/null then download_sources else export SOURCE_DIR=/tmp/sourcedir umount "$SOURCE_DIR" &> /dev/null || true rm -rf "$SOURCE_DIR" mkdir -p "$SOURCE_DIR" mount -t tmpfs none "$SOURCE_DIR" ( cd "$SOURCE_DIR" curlwrapper -L "https://github.com/${REPO}/teslausb/archive/${BRANCH}.tar.gz" | tar zxf - --strip-components=1 ) fi fi cp "${SOURCE_DIR}/$remote_path" "$local_path/$name" chmod +x "$local_path/$name" setup_progress "Downloaded $local_path/$name ..." } function safesource { cat < /tmp/checksetupconf #!/bin/bash -eu source '$1' &> /tmp/checksetupconf.out EOF chmod +x /tmp/checksetupconf if ! /tmp/checksetupconf then setup_progress "Error in $1:" setup_progress "$(cat /tmp/checksetupconf.out)" exit 1 fi # shellcheck disable=SC1090 source "$1" } THISDIR=$(dirname "$(readlink -f "$0")") if [ ! -e "$THISDIR/envsetup.sh" ] then # source the conf file directly to get REPO, BRANCH or download_sources # in case they're set safesource /root/teslausb_setup_variables.conf REPO=${REPO:-marcone} BRANCH=${BRANCH:-main-dev} copy_script setup/pi/envsetup.sh "$THISDIR" fi # SC can't follow non-constant source # shellcheck disable=SC1090 source "$THISDIR/envsetup.sh" function dehumanize () { echo $(($(echo "$1" | sed 's/GB/G/;s/MB/M/;s/KB/K/;s/G/*1024M/;s/M/*1024K/;s/K/*1024/'))) } REBOOT=false # wpa_supplicant should have a country code. Use US as the default # to avoid using the disallowed channels in the US. WPA=/etc/wpa_supplicant/wpa_supplicant.conf if [ -e "$WPA" ] && ! grep -q "country=" $WPA && grep -q "network=" $WPA then setup_progress "adding country code to wpa_supplicant.conf" echo "country=US" >> $WPA REBOOT=true fi BOOT_DISK=$(lsblk -dpno pkname "$(findmnt -D -no SOURCE --target /teslausb)") declare -rx BOOT_DISK BOOT_PARTITION_DEVICE=$(lsblk -dpno name "$(findmnt -D -no SOURCE --target /teslausb)") readonly BOOT_PARTITION_DEVICE readonly BOOT_DEVICE_PARTITION_PREFIX=${BOOT_PARTITION_DEVICE%?} export BOOT_DEVICE_PARTITION_PREFIX ROOT_PARTITION_DEVICE=$(lsblk -dpno name "$(findmnt -D -no SOURCE --target /)") declare -rx ROOT_PARTITION_DEVICE readonly ROOT_PART_NUM=${ROOT_PARTITION_DEVICE:0-1} INCREASE_ROOT_SIZE=$(($(dehumanize "$INCREASE_ROOT_SIZE") / 512)) if [ "$INCREASE_ROOT_SIZE" != "0" ] && [ ! -e "${BOOT_DEVICE_PARTITION_PREFIX}$((ROOT_PART_NUM+1))" ] then if [ ! -e /root/TESLAUSB_ROOT_PARTITION_INCREASED ] then touch /root/TESLAUSB_ROOT_PARTITION_INCREASED ROOTSTART=$(partx --show -g -o START "${ROOT_PARTITION_DEVICE}") ROOTSIZE=$(partx --show -g -o SECTORS "${ROOT_PARTITION_DEVICE}") ROOTSIZE=$((ROOTSIZE + INCREASE_ROOT_SIZE)) echo "$ROOTSTART,$ROOTSIZE" | sfdisk --force "${BOOT_DISK}" -N "${ROOT_PART_NUM}" setup_progress "increased root partition size" REBOOT=true else setup_progress "increasing root filesystem size to match partition size" resize2fs "${ROOT_PARTITION_DEVICE}" fi fi if [ "$REBOOT" = "true" ] then if [ -t 0 ] && [ "${NO_REBOOT_PROMPT:-}" != "1" ] then setup_progress "please reboot for changes to take effect" exit else setup_progress "rebooting for changes to take effect" reboot exit fi fi function headless_setup_mark_setup_success () { rm -f /teslausb/TESLAUSB_SETUP_FAILED rm -f /teslausb/TESLAUSB_SETUP_STARTED touch /teslausb/TESLAUSB_SETUP_FINISHED } function flash () { local ON=0 local OFF=1 if isPi4 || isPi5 then ON=1 OFF=0 fi echo none > "$STATUSLED/trigger" echo $OFF > "$STATUSLED/brightness" sleep 1 for ((i=1; i<=$1; i++)) do echo $ON > "$STATUSLED/brightness" sleep .2 echo $OFF > "$STATUSLED/brightness" sleep .8 done } function headless_setup_progress_flash () { if [ ! -t 0 ] then flash "$1" fi } function verify_configuration () { copy_script setup/pi/verify-configuration.sh /tmp /tmp/verify-configuration.sh } function get_common_scripts () { setup_progress "Downloading common runtime scripts." copy_script run/remountfs_rw /root/bin copy_script run/make_snapshot.sh /root/bin copy_script run/release_snapshot.sh /root/bin copy_script run/manage_free_space.sh /root/bin copy_script run/force_sync.sh /root/bin copy_script run/mountoptsforimage /root/bin copy_script run/mountimage /root/bin copy_script run/enable_gadget.sh /root/bin copy_script run/disable_gadget.sh /root/bin ln -sf /root/bin/mountimage /sbin/mount.teslausb } # If only the dwc2 module is loaded at boot then the Pi will present # itself as a non-responsive USB device until a gadget is created. # When connected to a Windows host, this will show as a device with # vendor ID 0 (which is invalid), and Windows might pop up an error # message saying "USB device not recognized", while a connected Linux # host will log messages like "device descriptor read/64, error -110" # to the kernel log, and 'lsusb' might hang for over a minute or until # a gadget is created. # To work around this, make sure the g_ether module is loaded along # with dwc2. The archiveloop script will then unload the g_ether # module (the attached host will see no device at all at this point) # before creating the mass storage gadget. function fix_cmdline_txt_modules_load () { if [ ! -f "$CMDLINE_PATH" ] then setup_progress "cmdline.txt does not exist, skipping" return fi # Extract the modules-load portion of the command line. # Note that this not handle spaces in the argument. local curparam curparam=$(grep -P -o " modules.load=[^\s\$]*" "$CMDLINE_PATH" || true) if [[ "$curparam" == "" ]] then curparam="\$" elif [[ "$curparam" == *"dwc2"* ]] && [[ "$curparam" == *"g_ether"* ]] then setup_progress "cmdline.txt is up to date" return fi # replace the current parameter setup_progress "Updated cmdline.txt from:" setup_progress "$(cat "$CMDLINE_PATH")" sed -i "s/${curparam}/ modules-load=dwc2,g_ether/" "$CMDLINE_PATH" setup_progress "to:" setup_progress "$(cat "$CMDLINE_PATH")" } BACKINGFILES_MOUNTPOINT=/backingfiles MUTABLE_MOUNTPOINT=/mutable function update_backingfiles_fstab_entry () { local filename="$1" local mountpoint="$2" sed -i "\@^$filename .*@d" /etc/fstab if [ -e "$filename" ] then mkdir -p "$mountpoint" echo "$filename $mountpoint teslausb noauto 0 0" >> /etc/fstab setup_progress "updated /etc/fstab for $mountpoint" fi } function mount_with_retry () { for i in {1..5} do if mount "$@" then return fi setup_progress "'mount $*' failed, retrying" sleep 1 done return 1 } function create_usb_drive_backing_files () { if [ ! -e "$BACKINGFILES_MOUNTPOINT" ] then mkdir "$BACKINGFILES_MOUNTPOINT" fi if [ ! -e "$MUTABLE_MOUNTPOINT" ] then mkdir "$MUTABLE_MOUNTPOINT" fi copy_script setup/pi/create-backingfiles-partition.sh /tmp /tmp/create-backingfiles-partition.sh "$BACKINGFILES_MOUNTPOINT" "$MUTABLE_MOUNTPOINT" if ! findmnt --mountpoint $BACKINGFILES_MOUNTPOINT > /dev/null then setup_progress "Mounting the partition for the backing files..." mount $BACKINGFILES_MOUNTPOINT setup_progress "Mounted the partition for the backing files." fi if ! findmnt --mountpoint $MUTABLE_MOUNTPOINT > /dev/null then setup_progress "Mounting the mutable partition..." mount $MUTABLE_MOUNTPOINT setup_progress "Mounted the mutable partition." fi setup_progress "Creating backing disk files." copy_script setup/pi/create-backingfiles.sh /tmp /tmp/create-backingfiles.sh "$CAM_SIZE" "$MUSIC_SIZE" "$LIGHTSHOW_SIZE" "$BOOMBOX_SIZE" "$BACKINGFILES_MOUNTPOINT" "$USE_EXFAT" update_backingfiles_fstab_entry $BACKINGFILES_MOUNTPOINT/cam_disk.bin /mnt/cam update_backingfiles_fstab_entry $BACKINGFILES_MOUNTPOINT/music_disk.bin /mnt/music update_backingfiles_fstab_entry $BACKINGFILES_MOUNTPOINT/lightshow_disk.bin /mnt/lightshow update_backingfiles_fstab_entry $BACKINGFILES_MOUNTPOINT/boombox_disk.bin /mnt/boombox # mount cam image and make sure the right directories exist umount /mnt/cam > /dev/null || true local ret=0 /root/bin/disable_gadget.sh || ret=$? if (( (ret == 0) || (ret == 2) )) then if [ -e /backingfiles/cam_disk.bin ] && mount_with_retry /mnt/cam then mkdir -p /mnt/cam/TeslaCam mkdir -p /mnt/cam/TeslaTrackMode touch /mnt/cam/.metadata_never_index local -r sentrylist_previously_archived=/mutable/sentry_files_archived # For upgrades from before snapshot-archiving, assume everything from the # snapshots -except the files still on the disk image- was already archived, # to avoid re-archiving things that were manually deleted from the archive # server. if [ ! -e "$sentrylist_previously_archived" ] && [ -d "$MUTABLE_MOUNTPOINT/TeslaCam" ] then find "$MUTABLE_MOUNTPOINT/TeslaCam" -type l -printf '%P\n' | sort > /tmp/allfiles.txt find /mnt/cam/TeslaCam /mnt/cam/ -type f -printf '%P\n' | sort > /tmp/stilloncard.txt comm -2 -3 /tmp/allfiles.txt /tmp/stilloncard.txt > "$sentrylist_previously_archived" rm -f /tmp/allfiles.txt /tmp/stilloncard.txt fi umount -l /mnt/cam || setup_progress "failed to unmount /mnt/cam" fi if [ -e /backingfiles/music_disk.bin ] && mount_with_retry /mnt/music then touch /mnt/music/.metadata_never_index umount -l /mnt/music || setup_progress "failed to unmount /mnt/music" fi if [ -e /backingfiles/lightshow_disk.bin ] && mount_with_retry /mnt/lightshow then mkdir -p /mnt/lightshow/LightShow touch /mnt/lightshow/.metadata_never_index umount -l /mnt/lightshow || setup_progress "failed to unmount /mnt/lightshow" fi if [ -e /backingfiles/boombox_disk.bin ] && mount_with_retry /mnt/boombox then mkdir -p /mnt/boombox/Boombox touch /mnt/boombox/.metadata_never_index umount -l /mnt/boombox || setup_progress "failed to unmount /mnt/boombox" fi else setup_progress "STOP: Couldn't check image" exit 1 fi } function configure_hostname () { local new_host_name="$TESLAUSB_HOSTNAME" local old_host_name old_host_name=$(hostname) # Set the specified hostname if it differs from the current name if [ "$new_host_name" != "$old_host_name" ] then setup_progress "Configuring the hostname..." sed -i -e "s/$old_host_name/$new_host_name/g" /etc/hosts sed -i -e "s/$old_host_name/$new_host_name/g" /etc/hostname while ! hostnamectl set-hostname "$new_host_name" do if [ ! -e /lib/systemd/system/dbus.service ] then break fi setup_progress "hostnamectl failed, retrying" sleep 1 done systemctl restart avahi-daemon || true setup_progress "Configured hostname: $(hostname)" fi } function make_root_fs_readonly () { copy_script setup/pi/make-root-fs-readonly.sh /tmp /tmp/make-root-fs-readonly.sh } function update_package_index () { setup_progress "Updating package index files..." # the package index might be in a bad state if setup was previously # interrupted, so fix it up first dpkg --configure -a || true while ! (apt-get update || apt-get update --allow-releaseinfo-change) do setup_progress "Failed, retrying" sleep 2 done } function upgrade_packages () { if [ "$UPGRADE_PACKAGES" = true ] then setup_progress "Upgrading installed packages..." # clean the cache to free up space, since especially # a kernel update requires quite a bit of temporary # extra space apt-get clean apt-get --assume-yes upgrade else setup_progress "Skipping package upgrade." fi # no real need to keep the cache around after setup apt-get clean fstrim / || true } function set_timezone () { if [ -n "${TIME_ZONE:+x}" ] then if [ -f "/usr/share/zoneinfo/$TIME_ZONE" ] then ln -sf "/usr/share/zoneinfo/$TIME_ZONE" /etc/localtime elif [ "$TIME_ZONE" = "auto" ] then if curlwrapper -o /root/bin/tzupdate.py https://raw.githubusercontent.com/marcone/tzupdate/develop/tzupdate.py then chmod +x /root/bin/tzupdate.py if ! tzout=$(/root/bin/tzupdate.py 2>&1) then setup_progress "auto timezone failed: $tzout" else setup_progress "$tzout" fi fi else setup_progress "invalid timezone: $TIME_ZONE" fi fi } # There's probably a better way of doing this. # If not, there should be. function get_usb_state { local current local last; current=$(cat /sys/class/udc/*/state) echo -n "Gadget state: $current" if [ "$current" = "configured" ] then echo return fi last=$(dmesg | grep 'g_mass_storage\|dwc2' | tail -1) if [ -z "$last" ] then echo ". No UMS/dwc2 messages in dmesg" return fi local usbstatetime usbstatetime=$(echo "$last" | tr -d '[]' | awk '{print $1}') now=$(awk '{print $1}' /proc/uptime) awk "BEGIN {printf \". %.1f seconds ago: \", $now-$usbstatetime}" case $last in # this message is now a debug log and doesn't show in normal builds *"Linux File-Backed Storage") echo "connected to host and host mounted drive(s)" ;; *"new device"*) ;& *"new address"*) echo "connected to host" ;; *"bound driver"*) echo "mass storage ready, but not connected to host (check cable)" ;; *) echo "unknown": esac } function cmd_install { /root/bin/remountfs_rw copy_script "$1" /root/bin setup_progress "$1 installed in /root/bin/" exit } function cmd_selfupdate { echo "The 'selfupdate' command is no longer supported. Run '$0 upgrade' instead." exit 0 } function cmd_upgrade { if [ ! -e /teslausb/TESLAUSB_SETUP_FINISHED ] then echo "STOP: previous setup didn't finish, can't upgrade unfinished install" exit 1 fi copy_script setup/pi/setup-teslausb /tmp &> /dev/null copy_script setup/pi/envsetup.sh /tmp &> /dev/null exec bash -c "/tmp/setup-teslausb upgrade_prepare && NO_REBOOT_PROMPT=1 /tmp/setup-teslausb && /tmp/setup-teslausb upgrade_finish" } function cmd_upgrade_prepare { setup_progress "preparing for full upgrade" ( systemctl stop teslausb || true killall archiveloop || true service smbd stop || true service autofs stop || true umount /backingfiles/snapshots/snap*/mnt || true umount /mnt/cam /mnt/music || true umount /mnt/lightshow || true umount /mnt/boombox || true umount /mnt/archive /mnt/musicarchive || true /root/bin/disable_gadget.sh || true /root/bin/remountfs_rw # a previous bookworm install may have the makers in /boot, so move # them to /teslausb (/boot/firmware) if [ ! /boot -ef /teslausb ] then for i in WIFI_ENABLED TESLAUSB_SETUP_STARTED TESLAUSB_SETUP_FINISHED do if [ -e "/boot/$i" ] then mv "/boot/$i" /teslausb fi done fi ) &> /dev/null } function cmd_upgrade_finish { mv /tmp/setup-teslausb /root/bin/setup-teslausb mv /tmp/envsetup.sh /root/bin/envsetup.sh setup_progress "upgrade finished" for i in {5..1} do echo -e -n "rebooting in $i seconds to apply changes, press ctrl-c to abort\r" sleep 1 done echo -e '\nRebooting' reboot } function checkmounted() { if ! findmnt "$1" &> /dev/null then echo "ERROR: $1 is not mounted" fi } function checkfsrw() { local -r opts=$(findmnt -n -o options "$1") local -r rw=${opts:0:2} if [[ "$rw" != "$2" ]] then echo "$1 is $rw, should be $2" fi } function boot_is_not_on_root { [ "$(stat -c "%d" /)" -ne "$(stat -L -c "%d" /teslausb)" ] } function diagnose { local hardware local os hardware=$( tr -d '\000' < /sys/firmware/devicetree/base/model ) os=$(. /etc/os-release && echo "$PRETTY_NAME") { echo -e "====== summary ======" echo -e "hardware: ${hardware}" echo -e "OS: ${os}" if [ "${ARCHIVE_SYSTEM:-unset}" = "unset" ] then echo "ERROR: no archive method specified!" elif [ "${ARCHIVE_SYSTEM:-none}" = "cifs" ] then if grep -q '/mnt/archive' /etc/fstab then echo "CIFS archiving selected" else echo "ERROR: CIFS archiving selected, but archive not defined in fstab" fi elif [ "${ARCHIVE_SYSTEM:-none}" = "rclone" ] then if [ ! -e "/root/.config/rclone/rclone.conf" ] then echo "ERROR: rclone archiving selected, but rclone config does not exist" elif [ ! -L "/root/.config/rclone" ] then echo "ERROR: rclone archiving selected, but rclone config is in /root" else echo "rclone archiving selected" fi else echo "archive method: ${ARCHIVE_SYSTEM:-unset}" fi if [[ "$DATA_DRIVE" != "" ]] && (isPi4 || isPi5) then echo "DATA_DRIVE=$DATA_DRIVE: consider booting from USB instead." fi if ! blkid -L backingfiles > /dev/null then echo "ERROR: backingfiles partition does not exist" fi if [ ! -d /backingfiles ] then echo "backingfiles directory does not exist" fi if ! grep -q '/backingfiles' /etc/fstab then echo "ERROR: backingfiles not in fstab" fi if [ ! -f /backingfiles/cam_disk.bin ] then echo "ERROR: cam disk image does not exist" fi if ! grep -q '/backingfiles/cam_disk.bin' /etc/fstab then echo "ERROR: cam disk image not in fstab" fi for i in 0 1 2 3 4 5 6 do LUN="/sys/kernel/config/usb_gadget/teslausb/functions/mass_storage.0/lun.${i}/file" if [ -e "$LUN" ] then echo "lun${i} connected, from file $(cat "$LUN")" fi done if ! blkid -L mutable > /dev/null then echo "ERROR: mutable partition does not exist" fi if [ ! -d /mutable ] then echo "ERROR: mutable directory does not exist" fi if ! grep -q '/mutable' /etc/fstab then echo "ERROR: mutable not in fstab" fi if [ -n "${SNAPSHOT_INTERVAL:+x}" ] then echo "Snapshot interval: $SNAPSHOT_INTERVAL" fi numsnapshots=$( mount | grep -c snapshot ) echo "$numsnapshots snapshots mounted" if [ ! -e /teslausb/TESLAUSB_SETUP_FINISHED ] then echo 'ERROR: setup did not finish' fi get_usb_state local -r archiveloopcount=$(pgrep -f archiveloop | wc -l) if ((archiveloopcount <= 2)) then echo "archiveloop is not running" journalctl -u teslausb | tail -30 fi local -r inodes=$(df --output=ipcent /mutable/ | sed 1d | sed 's/[^0-9]//g') if [[ "$inodes" -gt 80 ]] then echo "WARNING: /mutable is low on inodes: ${inodes}% used" fi if [[ "$BRANCH" != "main-dev" || "$REPO" != "marcone" ]] then echo "WARNING: using $REPO/$BRANCH" fi if [ -x /root/bin/archive-filter ] then echo "Custom archive filter is in use" fi read -r offset <<<"$(sfdisk -l -q -o START /backingfiles/cam_disk.bin | tail -1)" fstype=$(blkid --probe -o value -s TYPE --offset $((offset*512)) /backingfiles/cam_disk.bin) if [ "$fstype" = "exfat" ] then echo "CAM drive is formatted as ExFAT. Recommend using FAT32 instead." fi checkfsrw / ro if boot_is_not_on_root then checkfsrw /teslausb ro fi checkfsrw /backingfiles rw checkfsrw /mutable rw checkmounted /var/www/html/TeslaCam checkmounted /var/www/html/fs echo -e "====== disk / images ======" parted -s "${BOOT_DISK}" print || true if [ -n "${DATA_DRIVE:+x}" ] then parted -s "$DATA_DRIVE" print || true fi if [ -f /backingfiles/cam_disk.bin ] then echo "cam disk image has $(filefrag /backingfiles/cam_disk.bin | awk '{print $2}') extents" parted -s /backingfiles/cam_disk.bin print || true else echo "no cam disk image found" fi if [ -f /backingfiles/music_disk.bin ] then echo "music disk image has $(filefrag /backingfiles/music_disk.bin | awk '{print $2}') extents" parted -s /backingfiles/music_disk.bin print || true else echo "no music disk image found" fi if [ -f /backingfiles/lightshow_disk.bin ] then echo "lightshow disk image has $(filefrag /backingfiles/lightshow_disk.bin | awk '{print $2}') extents" parted -s /backingfiles/lightshow_disk.bin print || true else echo "no lightshow disk image found" fi if [ -f /backingfiles/boombox_disk.bin ] then echo "boombox disk image has $(filefrag /backingfiles/boombox_disk.bin | awk '{print $2}') extents" parted -s /backingfiles/boombox_disk.bin print || true else echo "no boombox disk image found" fi df -h /teslausb/ / /backingfiles/ /mutable/ echo -e "====== network ======" ifconfig iwconfig wlan0 | grep Link echo -e "====== fstab ======" if [ -e /etc/fstab ] then cat /etc/fstab else echo "no fstab found" fi echo -e "====== mounts ======" mount echo -e "====== initial setup boot log ======" mkdir /tmp/root$$ mount --bind / /tmp/root$$ if [ -e /tmp/root$$/var/log/boot.log ] then cat /tmp/root$$/var/log/boot.log else echo "no boot log found" fi umount /tmp/root$$ rmdir /tmp/root$$ echo -e "====== rc.local log ======" journalctl -u rc-local echo -e "====== setup log ======" if [ -e /teslausb/teslausb-headless-setup.log ] then cat /teslausb/teslausb-headless-setup.log else echo "no setup log found" fi echo -e "====== archiveloop log ======" if [ -e /mutable/archiveloop.log ] then cat /mutable/archiveloop.log else echo "no archiveloop log found" fi echo -e "====== system log ======" if [ -x /bin/logread ] then /bin/logread else echo "logread not installed" fi echo -e "====== dmesg ======" dmesg -T echo -e "====== process list and uptime ======" ps -eaf echo "$(hostname) has been $(uptime -p). System time is $(date)" echo -e "====== end of diagnostics ======" } } function cmd_diagnose { { diagnose || true; } |& # clean up the output a bit tr '\r' '\n' | sed '/^ *$/d' | grep -a -v '^Reading package lists' | grep -a -v '^(Reading database' | grep -a -v "^Adding 'diversion of" | grep -a -v "^Removing 'diversion of" | sed -E 's/\o033\[0;32m//' | sed -E 's/\o033\[0m//' } export -f setup_progress INSTALL_DIR=${INSTALL_DIR:-/root/bin} if [ "$INSTALL_DIR" != "/root/bin" ] then setup_progress "WARNING: 'INSTALL_DIR' setup variable no longer supported" fi BRANCHNAME="$BRANCH" if [ -n "${1:+x}" ] then command=cmd_$1 if typeset -f "$command" > /dev/null then shift $command "$@" exit 0 else setup_progress "unknown command: $1" exit 1 fi fi # Turn on all leds in case they're still flashing # from pre-setup. for led in /sys/class/leds/* do if [ -e "$led/trigger" ] then echo none > "$led/trigger" || true echo 1 > "$led/brightness" || true fi done # Update config.txt if needed if [ -f "$PICONFIG_PATH" ] then if ! grep -q 'dtoverlay=dwc2$' "$PICONFIG_PATH" then echo -e "dtoverlay=dwc2\n" >> "$PICONFIG_PATH" setup_progress "rebooting to apply dwc2 overlay change" reboot exit 0 fi fi configure_hostname tmpdir=/tmp/$$ mkdir -p "$tmpdir" copy_script setup/pi/setup-teslausb "$tmpdir" &> /dev/null if cmp -s "$tmpdir/setup-teslausb" "$0" then setup_progress "$0 is up to date" else setup_progress "WARNING: $BRANCHNAME contains a different version of $0. It is recommended to run '$0 upgrade' to get the latest version." fi copy_script pi-gen-sources/00-teslausb-tweaks/files/rc.local "$tmpdir" &> /dev/null if cmp -s "$tmpdir/rc.local" /etc/rc.local then setup_progress "rc.local is up to date" else setup_progress "updating rc.local" mv "$tmpdir/rc.local" /etc/rc.local parent=$(ps -o ppid= $PPID) grandparent=$(ps -o ppid= "$((parent))" ) caller=$(ps -o comm= "$((grandparent))") if [ "$caller" = "rc.local" ] && [ ! -t 0 ] then setup_progress "rebooting to run updated rc.local" exec reboot fi fi update_package_index # set time zone so we get decent timestamps in the rest of the setup log set_timezone # Flash for stage 2 headless (verify requested configuration) headless_setup_progress_flash 2 setup_progress "Verifying that the requested configuration is valid..." verify_configuration # Flash for Stage 3 headless (grab scripts) headless_setup_progress_flash 3 mkdir -p /root/bin get_common_scripts pushd ~ fix_cmdline_txt_modules_load # Flash for stage 4 headless (Create backing files) headless_setup_progress_flash 4 create_usb_drive_backing_files if [ "$CONFIGURE_ARCHIVING" = true ] then setup_progress "calling configure.sh" export -f curlwrapper export -f copy_script copy_script setup/pi/configure.sh /tmp /tmp/configure.sh else setup_progress "skipping configure.sh" fi if [ "$SAMBA_ENABLED" = "true" ] then export SAMBA_GUEST copy_script setup/pi/configure-samba.sh /tmp /tmp/configure-samba.sh fi if [ -n "${AP_SSID:+x}" ] then copy_script setup/pi/configure-ap.sh /tmp /tmp/configure-ap.sh fi copy_script setup/pi/configure-automount.sh /tmp /tmp/configure-automount.sh copy_script setup/pi/configure-web.sh /tmp /tmp/configure-web.sh copy_script setup/pi/configure-ssh.sh /tmp /tmp/configure-ssh.sh # source setup-teslausb from .bashrc to set up completion if ! grep -q envsetup.sh /root/.bashrc then echo "source /root/bin/envsetup.sh" >> /root/.bashrc fi sed -i '/source \/root\/bin\/setup-teslausb/d' /root/.bashrc # UX courtesy reminders if ! grep -q TESLAUSB_TIP1 /root/.bashrc then cat >> /root/.bashrc <<- EOC if [ -n "\$PS1" ]; then cat << TESLAUSB_TIP1 Run 'bin/setup-teslausb upgrade' to update to the latest version of teslausb, or run 'bin/remountfs_rw' to allow writing to the root partition. TESLAUSB_TIP1 fi EOC fi DEFUSER=$(grep ":1000:1000:" /etc/passwd | awk -F : '{print $1}') if [ -n "$DEFUSER" ] then if ! grep -q TESLAUSB_TIP1 "/home/$DEFUSER/.bashrc" then cat >> "/home/$DEFUSER/.bashrc" <<- EOC if [ -n "\$PS1" ]; then cat << TESLAUSB_TIP1 Run 'sudo -i' if you need to make changes. The TeslaUSB web interface is at http://$(hostname -s) or http://$(hostname -I | awk '{print $1}') TESLAUSB_TIP1 fi EOC fi if grep -q "/boot/TESLAUSB_SETUP_FINISHED" "/home/$DEFUSER/.bashrc" then sed -i "s@/boot/TESLAUSB_SETUP_FINISHED@/teslausb/TESLAUSB_SETUP_FINISHED@" "/home/$DEFUSER/.bashrc" fi if grep -q "/boot/TESLAUSB_SETUP_FINISHED" "/root/.bashrc" then sed -i "s@/boot/TESLAUSB_SETUP_FINISHED@/teslausb/TESLAUSB_SETUP_FINISHED@" "/root/.bashrc" fi fi make_root_fs_readonly upgrade_packages if [ -n "${INSTALL_USER_REQUESTED_PACKAGES:-}" ] then setup_progress "Installing user requested packages: ${INSTALL_USER_REQUESTED_PACKAGES}" read -r -a EXTRA_PACKAGES <<< "${INSTALL_USER_REQUESTED_PACKAGES[@]}" DEBIAN_FRONTEND=noninteractive apt-get -y --force-yes install "${EXTRA_PACKAGES[@]}" fi headless_setup_mark_setup_success # Flash for stage 5 headless (Mark success, FS readonly) headless_setup_progress_flash 5 setup_progress "All done." if [ -t 0 ] && [ "${NO_REBOOT_PROMPT:-}" != "1" ] then setup_progress '(reboot now for changes to take effect)' fi