Skip to content

Instantly share code, notes, and snippets.

@henri
Last active July 18, 2025 07:59
Show Gist options
  • Save henri/34f5452525ddc3727bb66729114ca8b4 to your computer and use it in GitHub Desktop.
Save henri/34f5452525ddc3727bb66729114ca8b4 to your computer and use it in GitHub Desktop.
start as many instances of a browser as you like (posix compliant)

🔒 SPB (start-private-browser)

Have you wished there was an easy way to interact with the web from your terminal? Maybe like me you feel ready to automate your web surfing from the tranquility of the shell? The bundled SPB fish snippits makes searching for information from the fish shell easy-as!

SPB presents the power to navigate the surging currents of our planets vast digital oceans right at your fingertips. SPB is a deceptivly simple shell script which will rapidly spawn one or more isolated browser sessons.

Swim happily ; SPB installs into your home directory (no need for sudo) and is easily removed in the event you don't make use of SPB each and every day. This GIST has everything you need to install and update SPB on your systems.

Harness the power of isolated web sessions with SPB. Every time you run SPB a new instance of Brave (a modern web browser) is spawned within a fresh screen session. When you close the browser, SPB will delete all web data related to that browser session from your computer.

This project is still in a seedling stage. If you find a bug please start a discussion. SPB is free software, if you enjoy using SPB then share a link with friends. This way you and your friends enjoy the benifits of SPB together!

💾 Installation

Kick-off install/upgrade by running the one liner four lines below in your terminal :

/bin/bash -c "$(curl -fsSL \
https://gist.githubusercontent.com/henri/\
34f5452525ddc3727bb66729114ca8b4/raw/\
500.spb-install-script.bash)"

Detailed install instructions : Copy and paste the lines above into a terminal and press enter.

Only run code from sources whom you trust. Inspect SPB source-code [ installer, project and fish snippits ] below.

The installer/update script is a convienince to simplify installation and updating of spb on your system(s). Updates are semi-automatic because in order to update you manually run the installer interactivly. Check the automated notes for details on configuring unattended spb updates and installations. Also, before enabling automatic updtes read the disclaimer section carfully.

If you prefer to use spb without using the install/update script (not reccomdned) ; copy the SBP project script to your system and make it executable.

📑 Usage

Once installation is complete. The following commands will get you started with SPB.

Start a new private browser session :

~/bin/start-private-browser.bash

Show SPB help :

~/bin/start-private-browser.bash --help | less

Update SPB :

~/bin/spb-update.bash

Update SPB help :

~/bin/spb-update.bash --help | less

Uninstall SPB from your system :

rm -ri ~/bin/start-private-browser.bash ~/bin/spb-update.bash ~/bin/spb-update.log ~/bin/spb-templates

⭐ Usage Examples

The real power of SPB is not so much with the basic usage listed above but with the abillity to create wrapper scripts or even simple functions which leverege SPB to perform specific operations automatically on your behalf.

Automations which leverage SPB may be something simple like performing a search, starting a chat. They may be more complex operatons controlled by scripts which will assist you with performing testing, benchmarking or any other series of steps which you need to be able to carry out more than once.

Below are examples to get you started with SPB to enhance every day web based tasks. More examples are to come which will provide expamples for testing, benchmarking, more advanced automations and leveraging AI agents. If you have created something which you feel may be useful to the SPB communitiy, start a discussion.

Handy wrapper scripts to facilitate SPB usage via the command line :

During installation if fish is installed, you will be prompted to automatically install these fish snippits. If you install fish after SPB and would like to install these snippits, just run the update command or re-install

Click on the 'snippit name' links below in order to show usage information relating to a specific snippit

command snippit name explanation
spb spb an alias to start-private-browser but shortedned to spb
spb-tor spb-tor start SPB with Tor network enabled ; equivilent to spb --tor
spb-ddg DuckDuckGo Search start multiple DuckDuckGo searches
spb-ddg-ai DuckDuckGo Chat have multiple DuckDuckGo AI (LLM) chats
spb-brave Brave Search start multiple Brave searches
spb-brave-ai Brave Browser Leo Summary begin multiple Brave AI (Leo) summerisations
spb-yt YouTube Search initate simultanius YouTube searches
spb-pai Perplexity AI Chat kick off converstations with Perplexity AI

If your system has fish installed and you run the update system in an unattended mode, then these snippits will be installed / updated. This is because that is the default option. When running in unattended mode all default options are selected. If you do not want the above snippits installed please run the update script interactivly and enter "no" when asked during the install process. Aagain the prompt for opting out is only available during interative mode when using spb-update.bash script or when manually running the install/update process.

The SPB project is not affiliated with any of the companies or the services listed above. Before using third party web services as listed above (eg Ai, Search, etc) it is reccomended that you first consult the services usage and privay policy. Many of these web based services offer a service in exchange for gathering and storing supplied information). Additional, examples like this are welcomed. If you put together something and would like, share a link to your work then comment below or start a discussion

SPB Templating Support

The built-in templating sub-system allows you to list, create, edit and load browser data templates. Essentially, this allows you to configure a browser just as you like and then load this template as needed for future browsing sessions. When you load an existing template a copy of the template is created for your session and then when you quit that copy is deleted. However, you still have the template and may start as many sepeate browser instances as you like form that template.

The templates are stored in the directory : ~/bin/spb-templates/

example command explanation
spb --new-template template-name Creates a new template and loads a browser
within which you may edit this newley created template.
Upon quit the template will be saved
spb --edit--template template-name Edits the existing template and load a browser
in which you may edit the the exiting template.
Upon quit the template will be updated
spb --template template-name Loads the existing template within a new browser. Upon quit
all data from the session is deleted.
spb --template template-name --standard Loads the specififed template.
But will not start in incogneto mode.
spb --list-tempaltes Presents a list of templates on your system.

🚩 Compatiability

Mild testing has been completed on the following operating systems :

  • GNU/LINUX

    • Linux Mint
      • apt-get update && apt-get install git fish coreutils
      • curl -fsS https://dl.brave.com/install.sh | sh
    • EndeavourOS
      • sudo pacman -Syu git fish coreutils grep
      • yay -S brave-bin
  • MacOS

    • Brew or MacPorts are the reccomedned approaches to managing SPB dependencies on MacOS
      • MacOS pacakge managers
        • Brew
          • brew install git fish coreutils
          • brew install --cask brave-browser
        • MacPorts
          • sudo port install git fish coreutils
          • Visit the Brave website and to manually install.
    • macOS 10.15 (and later)
    • Officially the latest versions of Chromium requires macOS 13 or later.

🛡️ Telemetry and Privacy

As you would expect. The SPB project has zero telemetry. As such if you decide to install and use this software nothing is sent back to mothership.

Note : If you schdule or manually run an install / update, then your system will poll and potentailly access this Github gist. As such, it is advisable that you read the section below regarding this project being hosted on GitHub. If this is a problem think twice before installing SPB or running SPB updates (manually / scheduled).

SPB is hosted on GitHub :octocat: and as such data is recorded ⏺️ as you access this page. At the bottom of this page you will find links to manage the way GitHub handles your data and tracking within a browser. Also, the following links are useful with regards understanding the stance of GitHub towards privacy and trust :

When automatiaclly or manually running the install / update commands, data from your system is sent to GitHub infrasturcture so that SPB is able to be installed / updated on your system. If this is a problem in your enviroment, it is suggested that you roll your own update system.

As the default browser option in SPB is Brave and that project is a telemetry sender ; it is advisable that you read the Brave privacy policy. Brave is an open source project. However, if having any kind of telemetry being sent out is a problem then you should opt to use a different browser. Also, follow and chime into this issue on github with your opinion(s) regarding telemetry opt-out features within Brave.

Different operating systems and even different LINUX distributions have different stances on privacy and telemetry. As such it is advisable that you check these details for your specific operating system. This project works on a variety of operating systems each with their own particulars relating to privacy and telemetry.

SPB Fish Snippits

Should you use spb-ddg, spb-ddg-ai or spb-pai fish snippits, then you will want to have a close look at the terms of service from DuckDuckGo and Perlexity Ai whose websites you will be accessing. If you are using spb-yt then be sure to check Googles privacy policy.

🔒 Security and Trust

You should only run code and use software from sources you trust! If you do not trust yourself to check the project code below or you do not trust my judgment, then it is reccomended to not run this code. The alternative is asking someone familar with shell scripting (the language used to create SPB) to vet the code on your behalf. Just make sure if you ask someone to help you vet the code ; that you also trust them. With 25+ years of experience writing shell scripts, you would hope that I have learnt to test my work.

Already have spb and fish snippits setup, you may issue the following command to have perplexity vet the code :

spb-pai "would you vet the following project code for malware : https://gist.github.com/henri/34f5452525ddc3727bb66729114ca8b4"

🔄 Automate Installation and Updates

The included spb-update.bash script may be run interactivly (see usage above). Alterativly, you may prefer to start it via a scheduling program (eg.cron) so that SPB regularly updates automatically.

Setup Automated Updates

If you would like to have SPB update automatically, then the spb-add-to-user-crontab.bash script will load a pre-defined crontab entry which will automatically update SPB each week using the spb-update.bash script. The step of running this auto-setup cron script is a manual. The setup of a cron job is not automated in any way beyond manually starting the spb-add-to-user-crontab.bash script. The easiest way to setup the crontab entry is to run the command below from a bash shell :

export SPB_CRON_SETUP="true"
/bin/bash -c "$(curl -fsSL \
https://gist.githubusercontent.com/henri/\
34f5452525ddc3727bb66729114ca8b4/raw/\
500.spb-install-script.bash)"

This is the same command used to install SPB, with one key difference : an enviroment varable SPB_CRON_SETUP is set to "ture" and exported.

The setup of unattended / automated SPB updates (eg. using the command above) will result in default choices being selected which you would normally be able to interactivly select. Also, see notes regarding telemitry and privacy if you schedule or manually start an SPB update.

Start Unatteded Updates (automtaically picks default choices)

Start an automated (unattended) update and monitor the progress by running the command below within a shell :

  ~/bin/spb-update.bash --auto-monitoring

Once the output stream completes (using the command above), press control-c to exit tail and return to your shell.

Roll Your Own

If you are looking to roll your own update system, then the notes below will assist you :

  • Pick a scheduling system (cron, launchd etc..) and add an entry
    • ensure that you export the following enviroment variable (examples for fish and bash are below) :
      • The example update script is written in bash and includes this enviroment varable export already.
        • fish
          • set --export SPB_SKIP_OVERWRITE_CHECK "true"
          • set --export SPB_UPDATE_SCRIPT_SKIP="true"
        • bash
          • export SPB_SKIP_OVERWRITE_CHECK="true"
          • export SPB_UPDATE_SCRIPT_SKIP="true"
        • You should also use a lock file to avoid more than one update running simultaneously
          • The lock file which is used by the update script is : /tmp/spb-update-$(hostname)-$(whoami).lock
    • Use the kick off script above to start the install / update.

All of the above and much more is handled for you if you use the included update script.

If you export proxy enviroment varables (as showen below) then the SPB install / update scripts will respect these settings and perform network operations via the specified proxy.

  # proxy settings for SPB install / update scripts
  
  # bash 
  export http_proxy="http://proxy.server:port"
  export https_proxy="https://proxy.server:port"
  
  # fish 
  set -x http_proxy "http://proxy.server:port"
  set -x export https_proxy "https://proxy.server:port"
  

📝 Licencing, Terms of Use and Legal

SPB is released under the GNU GPL 3 or later. The GNU GPL is a free software licence which protects users freedoms. Learn more about escaping to freedom.

🙋 Why is SPB needed?

The use cases for this script are immense and include simplified day-to-day web browsing, trouble-shooting, testing, load-testing, AI Agents performing multiple tasks or just having multiple tabs which are not related in terms of cookies etc.

When starting a private session within the Safari WebBrowser on MacOS each tab is seperate (the cookies are not shared between tabs). However, most other browsers share the private cookies with all private tabs. One approach is not better or worse. But if you would like to have multiple instances of a browser but not have them sharing all those dirty cookies, then this script allows you to start up all as many private (and separate) sessions as you need and as your system will cope with in terms of system resources. Have fun loading some private browsers.

May the privacy be with you!

:shipit:



⚠️ Disclaimer

SPB (start private browser) is able to start multiple private browsers. But do not expect more functionaility or privacy from running a browser in incogneto mode. The idea behind SPB is that you can load multiple instances which are somewhat seperated from one and other. Each instance is still running under your user accont and on your system.

In the event additional privcay is required run SPB within a VM or within a continer. If higher levels of privacy are needed, then consider these projects :

If you test it and it works on your operating system leave a comment :) or let me know it is not working. Currently there are no plans to make this work on Microsoft Windows. It may work within the WLS? Give it a try and let me know!

At this stage the script is configured by direct editing. At some point perhaps a config file will be a thing? See the road map for details.

If you decide to setup a scheduled automatic update, then you should trust that I am not going to add any malicious code into this system in the future and that the security of my systems are good enough to prevent someone else pushing malware into the code base. This applies to any software (not just SPB) which automatially updates (even if it is open source). You must alwasy trust the developers sufficiently if you enable auto-updates. This is why by design SPB will not automatically enable auto-updates. SPB expects that if you enable automatic updates you are intentionally placing trust in me to not mess with your system(s) deliberately and that I will secure my systems as the developer sufficiently to protect the SPB code base and build processes less, they break my security in order to take advantage of yours. Remember that any software system which automatically updates via the internet has these same risks.

This project is still in the 🌱 seedling stage (with lots of potetential). If you have suggestions / ideas to improve the way it works, then please start a discussion. If you test this on a particular operating system and it works or is not working for you please also leave a comment so that others know to give it a try or not :)

🚀 Contributing to the project

In order to protect users of this project all contributors must comply with the Developer Certificate of Origin. This ensures that all contributions are properly licensed and attributed.

🌏 External Resources

Development / Testing / Automation

General

#!/usr/bin/env bash
#
# Start many instances of Brave at the same time all within the same linux graphical login
# The general idea behind this script to start a private instance of brave-browser
# with local user data directory set to a directory within /tmp/ (by default)
#
# This also allows you to easily run multiple instances of the browser all with different
# startup options.
#
# This script may be easily modified to work with different Blink based browsers for example
# chromium, vivaldi, opera etc...
#
# Henri Shustak 2024
#
# Released under the GNU GPLv3 or later licence :
# https://www.gnu.org/licenses/gpl-3.0.en.html
#
# Project home page (featuring additional information and easy installation guide) :
# https://gist.github.com/henri/34f5452525ddc3727bb66729114ca8b4
#
# version 1.0 - initial release
# version 1.1 - added a check to make sure brave is installed before doing anything
# version 1.2 - added a basic help menu explaining the functionality (if you call it with -h or --help)
# version 1.3 - added basic support for FreeBSD and MacOS
# version 1.4 - added support for listing the running sessions (just list them via screen - nothing internal keeping track)
# version 1.5 - initial support for passing additional options to brave implimented (note : zero checking of option validity)
# version 1.6 - updates to the help output\
# version 1.7 - added url to download brave if it is not installed
# version 1.8 - added user-agent usage example
# version 1.9 - added additional sanity check
# version 2.0 - addeditional requirement check that screen is installed before doing anything
# version 2.1 - bug fix related to screen detection
# version 2.2 - minor improvement when listing active sessions
# version 2.3 - added additional usage notes
# version 2.4 - added improved support for displaying help
# version 2.5 - improved option parsing system
# version 2.6 - initial foundations for templating sub-system implimented
# version 2.7 - improved option parsing to allow for greater felxibility
# version 2.8 - increased verbosity of output while loading template data
# version 2.9 - added locking to the templates and squashed bugs
# version 3.0 - added standard option to not start incognito mode
# version 3.1 - added a quite mode option for less verbose output
# version 3.2 - prevent coping a template while it is being edited
# version 3.3 - improved template lock file session support, improved template support and squashed bugs
# version 3.4 - reporting and error handling relating to lock files improved
# version 3.5 - further improvments to template lock file subsystem reliability and user support dialog
# version 3.6 - cross platform compatibility enhancment
# version 3.7 - added a force stop command (to kill an spb session)
# version 3.8 - foundation laid for the template system to support browser comptability
# version 3.9 - further improvements to multi-browser support within the templating system
# version 4.0 - added update option support
# version 4.1 - minor improvments to output relating to updates
# version 4.2 - bug fixs
#
##
## Argument processing
##
# configuration variables
screen_session_prefix="brave-incognito" # prefix of the screen session name
temp_path="/tmp/browser" # location of temporary browser data
template_dir_parent="~/bin/spb-templates" # location of spb templates
template_browser_id_filename="spb-browser.id" # file which will contain the browser identifier for this template
update_script_path="~/bin/spb-update.bash"
update_script_arguments="--auto-monitoring"
# lock file varables to protect tempaltes being edited
spb_template_lock_file_name="spb-template-edit.lock"
spb_etlfr_cmd="" # spb edit template lock file remove command
# setup varabels for processing arguments we ares pecifcially NOT using get opts
args=("$@")
index=0
num_args=$#
# updated variables and the defaults
new_template_dir_name=""
edit_template_dir_name=""
use_template_dir_name=""
help_wanted="no"
update_wanted="no"
valid_argument_found="false"
standard_mode="false" # when set to true, we will not default to running incognito window
quite_mode="false"
force_stop_mode="false"
template_browser_id_absolute="" # when creating a new template this is set to the full absolute path to the template browser_id file
# internal argument parsing varables
skip_arg="false"
pre_arg_scan_proceed="true"
# pre argument scanning (arguments which will almost allways end up exiting before we actually start a browser)
for arg in "$@" ; do
# check for help wanted
if [[ "${arg}" == "-h" ]] || [[ "${arg}" == "--help" ]] ; then
help_wanted="yes"
valid_argument_found="true"
break
fi
# check for update wanted
if [[ "${arg}" == "--update" ]] ; then
update_wanted="yes"
valid_argument_found="true"
break
fi
# check for listing sessions (if found we will exit)
if [[ "${arg}" == "-ls" ]] || [[ "${arg}" == "-l" ]] || [[ "${arg}" == "--list" ]]; then
output_list=$(screen -ls | grep .${screen_session_prefix}- | awk '{print $1}' | sort -n)
if [[ "${output_list}" != "" ]] ; then
# output_list is not empty - list the items
echo "${output_list}"
exit 0
else
echo "SPB (start-private-browser) session was not detected."
exit -88
fi
fi
# list templates
if [[ "${arg}" == "--list-templates" ]] ; then
# if [[ ${index} != 0 ]] || [[ ${num_args} -gt 1 ]]; then
# echo ""
# echo "ERROR! : Using the ${arg} option is not compatiable with any other"
# echo " arguments / parameters."
# echo ""
# exit -79
# fi
ls ${template_dir_parent/#\~/$HOME} | cat
exit ${?}
fi
# forcefully close a browser session via identifier
if [[ "${arg}" == "--force-stop" ]] ; then
force_stop_mode="true"
fi
# check to see if quite mode should be enabled
if [[ "${arg}" == "--quite" ]] ; then
quite_mode="true"
valid_argument_found="true"
fi
done
# show usage information
if [[ "${help_wanted}" == "yes" ]] ; then
echo ""
echo " SPB or 'start-private-browser' is a wrapper to the brave-browser command."
echo ""
echo " This wrapper allows you to quickly start as many sperate instances"
echo " of the brave-browser as your system has available memory to run"
echo " simultianuusly under a single graphical login."
echo ""
echo " Requirments include gnu/screen and the brave-browser to be installed"
echo " on your system. This script has been mildly tested on gnu/linux mint."
echo " It is possible this will also work on many other posix compliant"
echo " opterating systems. Your miliage may vary."
echo ""
echo ""
echo " Usage Summary : "
echo ""
echo " # open a new private browser instance - optionally pass in a URL"
echo " $ start-private-browser [URL-TO-OPEN]"
echo ""
echo " # show list of private browser instances"
echo " $ start-private-browser --list"
echo ""
echo " # start the browser but no incognito option will be passed to the browser"
echo " $ start-private-browser --standard [URL-TO-OPEN]"
echo ""
echo " # surpress important notification output"
echo " $ start-private-browser --quite"
echo ""
echo " # forceably close a browser session if it has hung"
echo " $ start-private-browser --force-stop <instance-identifier>"
echo ""
echo " # update the spb system and assosiated fish snippits using default options"
echo " $ start-private-browser --update"
echo ""
echo ""
echo " Templates (Usage & Management) : "
echo ""
echo " # create a new template"
echo " $ start-private-browser --new-template <template-name>"
echo ""
echo " # list available templates"
echo " # start-private-browser --list-templates"
echo ""
echo " # edit an existing template"
echo " $ start-private-browser --edit-template <template-name>"
echo ""
echo " # load an existing template"
echo " $ start-private-browser --template <template-name>"
echo ""
echo ""
echo " Additional Resources : "
echo ""
echo " # additional argument information is viewable via the brave-browser man page : "
echo " $ man brave-browser"
echo ""
echo " # list of additional command line arguments : "
echo " https://support.brave.com/hc/en-us/articles/360044860011-How-Do-I-Use-Command-Line-Flags-in-Brave"
echo ""
echo ""
echo " Example Usage: "
echo ""
echo " # simply start a new private browser"
echo " $ start-private-browser "
echo ""
echo " # the same as above but open the browser page on the passed in URL"
echo " $ start-private-browser \"https://brave.com\""
echo ""
echo " # start a new private browser session using the tor network"
echo " $ start-private-browser --tor"
echo ""
echo " # pass additional argument (proxy in this example) to private browser"
echo " $ start-private-browser --proxy-server=\"http://myproxy.com:9090\" \"https://brave.com\""
echo ""
echo " # pass additional argument (app mode [eg no toolbars] in this example) to private browser"
echo " $ start-private-browser --app=\"https://brave.com\""
echo ""
echo " # start up private browser with multiple URLs"
echo " $ start-private-browser duckduckgo.com wolframalpha.com kagi.com"
echo ""
echo " # start browser with specific window position and open xkcd.com"
echo " $ start-private-browser --window-position=10,10 xkcd.com"
echo ""
echo " # start browser with larger / smaller user interface elements"
echo " $ start-private-browser --force-device-scale-factor=1.25 google.com"
echo " $ start-private-browser --force-device-scale-factor=0.95 google.com"
echo ""
echo " # start browser with spcific user-agent overide (example is FireFox for Windows)"
echo " $ start-private-browser --user-agent=\"Mozilla/5.0 (Windows NT x.y; Win64; x64; rv:10.0) Gecko/20100101 Firefox/10.0\""
echo ""
echo " # start a brave instance with remote debugging enabled"
echo " $ start-private-browser --remote-debugging-port=9222"
echo ""
echo " # connect to the remote debugging port on the local host (setup in the example above) using curl"
echo " $ curl \"http://localhost:9222/json\""
echo ""
echo ""
echo ""
exit 0
fi
# kick off update
if [[ "${update_wanted}" == "yes" ]] ; then
update_script_path_absolute="${update_script_path/#\~/$HOME}"
if [ -x ${update_script_path_absolute} ] ; then
updating_fish_snippits_message=""
if $(which fish >/dev/null) ; then
updating_fish_snippits_message=" and related fish snippits"
fi
echo ""
echo "Preparing to update SPB${updating_fish_snippits_message}."
echo ""
echo " If you have questions, do not proceed. You may consult the "
echo " spb-update.bash help by issuing the command directly below : " ; echo ""
echo " ${update_script_path} --help | less"
echo ""
echo " If you decide to proceed, then SPB${updating_fish_snippits_message}"
echo " will be updated by executing the following command :" ; echo ""
echo " ${update_script_path} ${update_script_arguments}" ; echo ""
echo -n " Do you wish to proceed with this update? [Y/n] : "
read auto_update_proceed
if \
[[ "${auto_update_proceed}" == "n" ]] || \
[[ "${auto_update_proceed}" == "N" ]] || \
[[ "${auto_update_proceed}" == "no" ]] || \
[[ "${auto_update_proceed}" == "No" ]] || \
[[ "${auto_update_proceed}" == "NO" ]] \
; then
echo ""
echo " Understood.. Update aborted."
echo ""
exit -164
fi
${update_script_path_absolute} ${update_script_arguments}
exit ${?}
else
echo "ERROR! : Unable to locate the SPB update script : ${update_script_path}"
exit -165
fi
fi
# function to valadate the template name
function check_template_name() {
local template_name=${1}
# prevent reserved template names from being used.
if [[ "${template_name}" == "available" ]] ; then
echo ""
echo "ERROR! : Using that template name \"${template_name}\" is not possible. It is reserved as a direrctory for"
echo " storing available templates which may enabled by symlinking them into the spb-template directory."
echo ""
exit -167
fi
# prevent template names being used that have spaces or non alpha-numeric characteers
if ! [[ "${template_name}" =~ ^[a-zA-Z0-9._-]+$ ]] ; then
echo ""
echo "ERROR! : Using that template name \"${template_name}\" is not possible."
echo " Supported template names must be alpha-numeric or supported special characters and they"
echo " must also not contain any spaces or tabs."
echo ""
echo " Support special characters allowed template names : "
echo ""
echo " - period [ \".\" ]"
echo " - hyphen [ \"-\" ]"
echo " - undersocre [ \"_\" ]"
echo ""
exit -167
fi
}
# process arguments using a for loop (yes it seems crazy but that is the way we are doing it)
# this is a custom arg parser in 2025 :)
for arg in "$@" ; do
# skip some paramaters passed into script
if [[ "${skip_arg}" == "true" ]] ; then
skip_arg="false"
((index++))
continue
fi
# look ahead for passed argument parameters
if (( index + 1 < num_args )) ; then
next_arg="${args[index + 1]}"
else
next_arg=""
fi
# force stop mode
if [[ "${force_stop_mode}" == "true" ]] ; then
if [[ "${arg}" == "--force-stop" ]] ; then
if [[ "${next_arg}" != "" ]] ; then
# valadate the argument provided
force_stop_identifier_valid=$(echo "${next_arg}" | grep ${screen_session_prefix} > /dev/null && echo true)
if [[ "${force_stop_identifier_valid}" == "true" ]] ; then
# force stop the instance provided
echo "Force Stop Mode"
echo " Killing Session : ${next_arg}"
screen -S ${next_arg} -p 0 -X stuff $'\003'
exit ${?}
else
echo ""
echo "ERROR! : The force stop argument provided is not valad."
echo ""
echo " List currently running (valid) instances by running : "
echo ""
echo " ~/bin/start-private-browser.bash --list"
echo ""
exit -148
fi
else
echo ""
echo "ERROR! : Unable to force stop any instance as no instance name was provided"
echo ""
echo " Force stop usage : "
echo ""
echo " ~/bin/start-private-browser.bash --force-stop <instance-identifier>"
echo ""
echo " List currently running instances : "
echo ""
echo " ~/bin/start-private-browser.bash --list"
echo ""
exit -149
fi
else
continue
fi
fi
# check for standard mode (not incognito)
if [[ "${arg}" == "--standard" ]] ; then
if [[ "${quite_mode}" != "true" ]] ; then
echo "Standard Mode Enabled"
fi
standard_mode="true"
valid_argument_found="true"
fi
# check for tempate or template editing
if [[ "${arg}" == "--template" ]] || [[ "${arg}" == "--edit-template" ]] || [[ "${arg}" == "--new-template" ]] ; then
# check they are not listed more than once
if [[ "${edit_template_dir_name}" != "" ]] || [[ "${use_template_dir_name}" != "" ]] || [[ "${new_template_dir_name}" != "" ]] ; then
echo ""
echo "ERROR! : Using the ${arg} option is only allowed once"
echo ""
exit -75
fi
if [[ "${next_arg}" != "" ]] ; then
# configure the system to skip the next argument for processing
# as it is the value for this one
skip_arg="true"
valid_argument_found="true"
check_template_name "${next_arg}"
# update template varables
if [[ "${arg}" == "--edit-template" ]] ; then
edit_template_dir_name="${next_arg}"
edit_template_dir_absolute="$(echo ${template_dir_parent/#\~/$HOME}/${edit_template_dir_name})"
if [[ "${quite_mode}" != "true" ]] ; then
echo "Editing existing SPB template : ${edit_template_dir_absolute}"
fi
elif [[ "${arg}" == "--new-template" ]] ; then
new_template_dir_name="${next_arg}"
new_template_dir_absolute="$(echo ${template_dir_parent/#\~/$HOME}/${new_template_dir_name})"
if ! [ -d $(echo ${template_dir_parent/#\~/$HOME}) ] ; then
mkdir $(echo ${template_dir_parent/#\~/$HOME})
if [[ ${?} == 0 ]] ; then
if [[ "${quite_mode}" != "true" ]] ; then
echo "Created SPB template direcotry : ${template_dir_parent/#\~/$HOME}"
fi
else
echo "" ; echo "ERROR! : Unable to create SPB template directory : ${template_dir_parent/#\~/$HOME}" ; echo ""
exit -23
fi
fi
if [ -d ${new_template_dir_absolute} ] ; then
# existing template was found
echo ""
echo "ERROR! : Unable to create new SPB template" ; echo ""
echo " Existing template with name \"${new_template_dir_name}\" already exists : "
echo " ${new_template_dir_absolute}" ; echo ""
echo " Perhaps you meant to use the [ --edit-template ] or [ --template ] option?"
echo ""
exit -22
else
# create the new template directrory
mkdir "${new_template_dir_absolute}"
if [[ ${?} == 0 ]] ; then
if [[ "${quite_mode}" != "true" ]] ; then
echo "Created new SPB template : ${new_template_dir_absolute}"
fi
else
echo "" ; echo "ERROR! : Unable to create new SPB template : ${new_template_dir_absolute}" ; echo ""
exit -21
fi
# setting this vaiable will result in browser informaiton being stored within this template
template_browser_id_absolute="${new_template_dir_absolute}/${template_browser_id_filename}"
# mop up the new mess as we will now be using the template
edit_template_dir_name="${new_template_dir_name}"
edit_template_dir_absolute="$(echo ${template_dir_parent/#\~/$HOME}/${edit_template_dir_name})"
new_template_dir_name=""
new_template_dir_absolute=""
fi
else
use_template_dir_name="${next_arg}"
use_template_dir_absolute="$(echo ${template_dir_parent/#\~/$HOME}/${use_template_dir_name})"
if [[ "${quite_mode}" != "true" ]] ; then
echo "Loading SPB template : ${use_template_dir_absolute}"
fi
# check that directory exists
if ! [ -d ${use_template_dir_absolute} ] ; then
echo ""
echo "ERROR! : Using the ${arg} option requires specifing a template name"
echo " which matches an existing template."
echo ""
echo " The template specified was not found : "
echo " ${template_dir_parent}/${use_template_dir_name}"
echo ""
exit -78
fi
fi
else
echo ""
echo "ERROR! : Using the ${arg} option requires specifing a template name"
echo " for an existing template directory."
echo ""
echo " Run command below for list of valid templates : "
echo " ~/bin/start-private-browser.bash --list-templates"
echo ""
exit -77
fi
fi
# this is disabled so we can pass arguments which are unknown along to brave...
# potentially we could have a list of accepted arguments to pass along (maybe?)
#
# # check if this is an argument starting with - or --
# arg_check=$(echo ${arg} | sed -n 's/^\(--\?\).*/\1/p')
# if [[ "${arg_check}" == "-" ]] || [[ "${arg_check}" == "--" ]] ; then
# if [[ "${valid_argument_found}" == "false" ]] ; then
# echo ""
# echo "ERROR! : Unknown argument provided : ${arg}"
# echo ""
# exit -79
# fi
# fi
((index++))
done
# prevent --edit-template and --template options being used togehter
if [[ "${edit_template_dir_name}" != "" ]] && [[ "${use_template_dir_name}" != "" ]] ; then
echo ""
echo "ERROR! : Using the the --template and --edit-template options together is not yet supported"
echo ""
exit -166
fi
##
## Pre flight checks
##
# check the operating system ; also check on brave and screen availability on system
os_type="$(uname)"
if [[ "${os_type}" == "Darwin" ]] ; then
# running on macOS
start_browser_path="/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"
mktemp_options="-d"
if [[ -x "${start_browser_path}" ]] ; then breave_browser_available=0 ; else breave_browser_available=1 ; fi
elif [[ "${os_type}" == "Linux" ]] || [[ "$(uname)" == "FreeBSD" ]]; then
# running on GNU/LINUX or FreeBSD
start_browser_path="brave-browser"
which ${start_browser_path} >> /dev/null ; breave_browser_available=${?}
mktemp_options="--directory"
else
echo "ERROR! : Unsupported operating system."
echo ""
echo " Please note this script requires a POSIX compliant"
echo " or at minimum a POSIX like operating system"
echo ""
echo -99
fi
# report if brave-browser is not available
if [[ ${breave_browser_available} != 0 ]] ; then
echo "ERROR! : Unable to locate brave-browser on your system."
echo ""
echo " Ensure that brave-browser is installed on your system and that the "
echo " correct path is configured within your PATH enviroment variable."
echo ""
echo " Instructions to install brave are available from the URL below : "
echo " https://brave.com/download/"
echo ""
exit -1
fi
# report if screen is not available
which screen >> /dev/null ; screen_available=${?}
if [[ ${screen_available} != 0 ]] ; then
echo "ERROR! : Unable to locate screen on your system."
echo ""
echo " Ensure that screen is installed on your system and that the "
echo " correct path is configured within your PATH enviroment variable."
echo ""
echo " Official instructions to install screen are available from the URL below : "
echo " https://www.gnu.org/software/screen/"
echo ""
echo " Non-Offical instructions to install screen on LINUX are available from the URL below : "
echo " https://linuxtldr.com/installing-screen/"
echo ""
echo " Non-Offical instructions to install screen on FreeBSD are available from the URL below : "
echo " https://joshdawes.com/installing-screen-for-freebsd/"
echo ""
exit -1
fi
# configure general template editing and loading varables
if [[ "${edit_template_dir_name}" != "" ]] || [[ "${use_template_dir_name}" != "" ]] ; then
if [[ "${edit_template_dir_name}" != "" ]] ; then
# this is a template we are editing
template_lock_file_absolute=${edit_template_dir_absolute}/${spb_template_lock_file_name}
else
# this is a template we will be using
template_lock_file_absolute=${use_template_dir_absolute}/${spb_template_lock_file_name}
fi
if [ -e ${template_lock_file_absolute} ] ; then
spb_screen_identifier_error_read_message="ERROR! : Unable read SBP screen identifier from lock file!"
spb_screen_session_template_lock_identifier=$(cat ${template_lock_file_absolute} || echo ${spb_screen_identifier_error_read_message})
if [[ "${spb_screen_session_template_lock_identifier}" == "" ]] ; then
spb_screen_session_template_lock_identifier="${spb_screen_identifier_error_read_message}"
fi
fi
fi
# function for reporting browser template locks
function report_general_browser_lock_file_information() {
echo ""
echo " SPB session identifier which locked this template :"
echo " ${spb_screen_session_template_lock_identifier}"
if [[ "${spb_screen_identifier_error_read_message}" == "${spb_screen_session_template_lock_identifier}" ]] ; then
echo " The lock file has some sort of issue."
fi
echo ""
echo " Currently running SPB session list : "
# list the running spb sessions on this system and highlight the locked file with grep
if [[ "${spb_screen_identifier_error_read_message}" == "${spb_screen_session_template_lock_identifier}" ]] ; then
$0 --list | sed 's/^[0-9][0-9]*\.//' | sed 's/^/ /'
else
$0 --list | sed 's/^[0-9][0-9]*\.//' | grep --color=always -e '^' -e ${spb_screen_session_template_lock_identifier} | sed 's/^/ /'
fi
echo ""
# check the running spb sessions and see if there is a match for the lock file
template_lock_file_culprit_found_in_running_spb_session="false"
if [[ "${spb_screen_identifier_error_read_message}" != "$spb_screen_session_template_lock_identifier" ]] ; then
template_lock_file_culprit_found_in_running_spb_session=$( $0 --list | sed 's/^[0-9][0-9]*\.//' | grep -x "${spb_screen_session_template_lock_identifier}" > /dev/null && echo "true")
fi
if [[ ${template_lock_file_culprit_found_in_running_spb_session} != "true" ]] ; then
echo " The SPB session identifier which reportedly locked this"
echo " template was ***NOT*** found in the list of running SPB sessions!"
echo ""
echo " Perhaps the machine was restarted or some other error"
echo " event occoured while the template was being edited?"
echo ""
echo " You could run the following command to manually remove the lock file :"
echo ""
echo " rm -i ${template_lock_file_absolute}"
echo ""
echo " Once removed, you could then attempt re-runing your command."
else
if [[ "${os_type}" != "Darwin" ]] ; then
echo " Sometimes browsers take a while to exit after you close the last window."
fi
if [[ "${os_type}" == "Darwin" ]] ; then
echo " Sometimes browsers take a while to exit after they have been quit."
echo ""
echo " Remember on macOS you must specifically quit the browser as closing"
echo " the browser windows, will not quit the browser. Select the browser"
echo " within the Dock and then select 'Quit' from the 'File' menu."
fi
echo " If you are sure your browser has exited ; wait a little"
echo " longer and then try re-running your command."
echo ""
process_id_to_kill=$($0 --list | grep "${spb_screen_session_template_lock_identifier}" | awk -F "." '{print $1}')
if [[ ${process_id_to_kill} != "" ]] ; then
echo " IMPORTANT NOTE : Rather than issuing either of the commands below. It is strongly"
echo " reccomended that you simply wait for the browser to shutdown gracefully ; in order"
echo " to avoid curruption of the template data."
echo ""
echo " If you decide to forcfully stop the process, consider issing the following command : "
echo " ~/bin/start-private-browser.bash --force-stop ${spb_screen_session_template_lock_identifier}"
echo ""
echo " The command above will send a control-c (AKA SIGINT or Signal Interrupt)"
echo " to the browser process (see importantnote above)."
echo ""
echo " Should that command above fail you may also consider killing the screen"
echo " process using the commad below (see important note above) :"
echo " kill ${process_id_to_kill}"
echo ""
echo " If you run either of the commands above, just wait a moment and then"
echo " proceed to re-run your command."
echo ""
fi
fi
echo ""
}
# template coping pre-flight checks
if [[ "${use_template_dir_name}" != "" ]] ; then
if [ -e ${template_lock_file_absolute} ] ; then
echo ""
echo "ERROR! : The template you are attempting to load contains an SPB edit lock :"
echo " ${template_lock_file_absolute}"
echo ""
echo " It is likley that you are currently editing this template."
echo " As such loading this the template is not possible."
report_general_browser_lock_file_information
if [[ "${spb_screen_session_template_lock_identifier}" == "${spb_screen_identifier_error_read_message}" ]] ; then
exit -211
fi
exit -58
fi
fi
# template editing pre-flight checks
if [[ "${edit_template_dir_name}" != "" ]] ; then
# confirm no lock file exits for this template
if [ -e ${template_lock_file_absolute} ] ; then
echo ""
echo "ERROR! : The template you are attempting to edit contains an SPB edit lock :"
echo " ${template_lock_file_absolute}"
echo ""
echo " You are probably already editing this template."
echo " As such, editing this the template is not possible."
report_general_browser_lock_file_information
if [[ "${spb_screen_session_template_lock_identifier}" == "${spb_screen_identifier_error_read_message}" ]] ; then
exit -212
fi
exit -56
fi
# create the lock file to prevent others from editing
if [[ "${quite_mode}" != "true" ]] ; then
echo " Creating template editing lock..."
fi
touch ${template_lock_file_absolute}
if [[ ${?} != 0 ]] ; then
echo ""
echo "ERROR! : Failed to create SPB edit lock :"
echo " ${template_lock_file_absolute}"
echo ""
echo " Check permissions for this SPB template."
echo " Editing this the template is not possible at this time."
echo ""
exit -57
fi
# configure edit template lock file removal command
spb_etlfr_cmd="; rm -f ${template_lock_file_absolute}"
fi
##
## Now we commence with take off
##
# create a tmporary directory and setup the permissions so that only your user has access to the direcotry
browser_tmp_directory=$(mktemp ${mktemp_options} ${temp_path}-$(whoami)-XXXXX)
if [[ $? != 0 ]] || [[ ! -d ${browser_tmp_directory} ]] ; then
echo "ERROR! : Unable to create temporary user data directory"
exit -2
fi
chmod 700 ${browser_tmp_directory}
if [[ $? != 0 ]] ; then
echo "ERROR! : Unable set permissions correctly for temporary user data directory"
exit -3
fi
# calculate the screen session name
screen_session_name="${screen_session_prefix}-$(echo "${browser_tmp_directory}" | awk -F "${temp_path}-" '{print$2}')"
# templating (copy the template over)
if [[ "${use_template_dir_name}" != "" ]] ; then
if [[ "${quite_mode}" != "true" ]] ; then
echo " Copying template data..."
fi
cp -r ${use_template_dir_absolute}/. ${browser_tmp_directory}/
if [[ ${?} != 0 ]] ; then
echo "ERROR! : Unable to copy template into place"
exit -5
fi
if [[ "${quite_mode}" != "true" ]] ; then
echo " Syncronizing filesystem..."
fi
sync
fi
# check if we are editing a template
if [[ "${edit_template_dir_name}" != "" ]] ; then
# saving the session details into the lock file
echo "${screen_session_name}" > ${template_lock_file_absolute}
if [[ ${?} != 0 ]] ; then
echo " WARNING! : Unable to save session details within the lock file."
fi
# temp directory is not used for this session (keeping the data and saving into the tempalte)
user_data_directory="--user-data-dir=${edit_template_dir_absolute}"
# create a sym-link within that directory to the template for clarity
if [[ "${quite_mode}" != "true" ]] ; then
echo " Linking to template data..."
fi
ln -s "${edit_template_dir_absolute}" ${browser_tmp_directory}/loaded_template.link 2>/dev/null
if [[ ${?} != 0 ]] ; then
echo "" ; echo " WARNING! : Unable establish symlink within temporary directory to the template."
fi
if [[ "${template_browser_id_absolute}" != "" ]] ; then
if [[ "${quite_mode}" != "true" ]] ; then
echo " Storing browser information..."
fi
"${start_browser_path}" --version > ${template_browser_id_absolute}
if [[ ${?} != 0 ]] ; then
echo "" ; echo " WARNING! : Unable save browser information into within the template."
fi
fi
if [[ "${quite_mode}" != "true" ]] ; then
echo " Syncronizing filesystem..."
fi
sync
else
# standard usage # using the temp directory (delete when browser closes)
user_data_directory="--user-data-dir=${browser_tmp_directory}"
fi
# are we running in standard mode
incognito_options="--incognito"
if [[ "${standard_mode}" == "true" ]] ; then
# not running incognito mode (eg standard mode)
incognito_options=""
fi
# parse the arguments for options and URL's to pass to brave.
browser_options="${user_data_directory} ${incognito_options}"
url_list=""
while [[ ${#} -ge 1 ]] ; do
# note, that no additional checking for validy of options is performed.
# maybe in a future version of this script.
if [[ $(echo "${1}" | grep -e "^-") ]] ; then
brave_option_name=$(echo "${1}" | sed -n 's/.*--\([^=]*\)=.*/\1/p')
brave_option_value=$(echo "${1}" | sed 's/^[^=]*=//')
if [[ ${brave_option_name} != "" ]] && [[ ${brave_option_value} != "" ]] ; then
new_brave_argument="--${brave_option_name}=\"${brave_option_value}\""
browser_options="${browser_options} ${new_brave_argument}"
else
browser_options="${browser_options} ${1}"
fi
else
if [[ "${1}" != "--edit_template_dir_name" ]] && [[ "${1}" != "--use_template_dir_name" ]] && [[ "${1}" != "${use_template_dir_name}" ]] && [[ "${1}" != "${edit_template_dir_name}" ]] ; then
# build the URL list (but exclude the template and edit-tempate data which may be have been provided)
url_list="${url_list} \"${1}\""
fi
fi
shift
done
# start a screen session with the name based off the temp directory, then once brave exits delete the temporary directory
screen -S "${screen_session_name}" -dm bash -c " \"${start_browser_path}\" ${browser_options} ${url_list} ; sleep 1 ; sync ; rm -rf ${browser_tmp_directory} ${spb_etlfr_cmd} "
exit 0
#!/usr/bin/env bash
#
# (C)Copyright Henri Shustak 2025
# Licenced Under the GNU GPL v3 or later
# https://www.gnu.org/licenses/gpl-3.0.en.html
#
# Simple build script to install
# the start-private-browser.bash
# and setup an alias within your
# shell - automatical styles !!!
#
# This script downloads spb files from this URL :
# https://gist.github.com/henri/34f5452525ddc3727bb66729114ca8b4/
#
# Once this script has successfully exectued, start a private browser with this command :
# ~/bin/start-private-browser.bash
#
# Initial release only supports zsh, fish and bash shell alias printing.
# Pull requests for other shell alias support bug fixes / reports welcome.
# Additional shells and further automation support will be added as time permits.
#
# version 1.0 - Initial Release
# version 1.1 - Added BASH shell alias setup output
# version 1.2 - Shallow clone (seems like a good idea)
# version 1.3 - Improved output somewhat specific to insalled shells displayed
# version 1.4 - Implimented additional error detection prior to temporary build directory deletion
# version 1.5 - Added enviroment variable to skip file overwriting (useful for automated upgrades)
# version 1.6 - Minor bug fix
# version 1.7 - Added ZSH shell alias setup output
# version 1.8 - Basic version reporting added
# version 1.9 - Implimented additional error checking and handling of unexpected conditions
# version 2.0 - Added additional output regarding the path of the file which if this is an upgrade
# version 2.1 - Dependency check added for git
# version 2.2 - Fixes to git dependency check messages
# version 2.3 - Added FISH alias function suggestion for spb -> start-private-browser
# version 2.4 - Added auto macOS /etc/defaults/periodic.conf edit option to prevent auto deletion spb browser directories"
# version 2.5 - Improvments and bug fixes to auto macOS edit options
# version 2.6 - Added option to setup fish snippits automatically if fish shell detected on system
# version 2.7 - Improved check mark cross platform compatibility
# version 2.8 - Improved enviroment varable skipping checks to facilitate auto-updates
# version 2.9 - Updates to output from git clone
# version 3.0 - Auto-update script installation included (not active)
# version 3.1 - Improved reliability of update process
# version 2.2 - Minor readme improvements regarding macOS /tmp/ dir edits
# version 2.3 - Added enviroment varable support to setup updates via users crontab
# version 2.4 - Bug fixes
#
# enviroment varibles setup
# set -e SPB_SKIP_OVERWRITE_CHECK "true" ; if you intend to run this script non-interactivly.
# if set to true, then overwiting of existing files will happen without any interactive
# prompt to bottle out ; this may result in data-loss. only intended for use during auto-updates!
if [[ "${SPB_SKIP_OVERWRITE_CHECK}" != "true" ]] ; then
# SPB_SKIP_OVERWRITE_CHECK enviroment varible not detected ; set to false (default)
SPB_SKIP_OVERWRITE_CHECK="false"
else
# if the spb skip is set to true ; then also set the fish function skip overwrite check to true as well
export SPB_FISH_FUNCTION_SKIP_OVERWRITE_CHECK="true"
fi
# additional enviroment variables setup
if [[ "${SPB_UPDATE_SCRIPT_SKIP}" != "true" ]] ; then
# SPB_UPDATE_SCRIPT_SKIP should be set to true, if this script is launced via the update script
SPB_UPDATE_SCRIPT_SKIP="false"
fi
if [[ "${SPB_CRON_SETUP}" != "true" ]] ; then
# SPB_CRON_SETUP enviroment varable shoul dbe set to true if you would like to setup an auto update crontab entry
SPB_CRON_SETUP="false"
fi
# check mark
tick_mark='\xE2\x9C\x94'
which git >> /dev/null ; git_available=${?}
if [[ ${git_available} != 0 ]] ; then
echo "ERROR! : The git command was not detected on your system."
echo " Ensure it is part of your path or install git onto your"
echo " system and try running this installer again."
echo ""
echo " Learn more about git the link below :"
echo " https://git-scm.com/"
echo ""
git # just see if the os reports anything helpful
exit -99
fi
# create a build directory, we will be sucking down the latest version of
# everything from git into this directory, then to clean up, we can delete :)
cd $( mktemp -d /tmp/spb-build.XXXXXXX )
if [[ $? != 0 ]] ; then
echo "ERROR! : Unable to setup the temporary build dirctory!"
exit -99
fi
# double sanity check (not needed) but lets avoid deleting anything important by mistake when we clean up
temporary_build_directory="$(pwd)"
if ! [[ $(echo "$(basename ${temporary_build_directory})" | grep "spb-build") ]] ; then
echo "ERROR! : Unable to succesfully locate the temporary directory"
exit -99
fi
# report the temporary build directory :
echo ""
echo "This script has created a temporay build directory : "
echo "$(pwd)"
echo ""
function elevate_privildges () {
# if running on macOS this is used to elevate permissions so that
# the file /etc/defaults/periodic.conf is able to be modified.
sudo -k # force password prompt
}
# clone a copy of the latest version into the temp directory
echo "Downloading latest version of SPB (start-private-browser)..."
git clone --progress --depth 1 --single-branch --branch=main https://gist.github.com/henri/34f5452525ddc3727bb66729114ca8b4 start-private-browser-latest 2>&1
if [[ $? != 0 ]] ; then
echo ""
echo "ERROR! : Sucking down latest version from git!"
echo " It is likely that git is not installed on"
echo " this system or there is a problem with"
echo " network access or possibly GitHub has"
echo " crashed or has been blocked?"
echo ""
echo " I am sure you will sort it out!"
exit -98
fi
# preform exit if we hit an error ; in addition set an EXIT trap
trap 'echo "" ; echo "Something went horribly wrong! Sorry please try again later." ; echo "" ; rm -f ~/bin/start-private-browser.bash.old.2delete' EXIT
set -e
# enter the local repo
cd start-private-browser-latest
downloaded_version=$(grep -E "^# version " ./050.start-private-browser.bash | tail -n 1 | awk '{print $3}')
# check if there is already a version installed?
spb_upgrade_install="install"
spb_upgrade_install_status="failure"
if [[ -f ~/bin/start-private-browser.bash ]] ; then
spb_upgrade_install="upgrade"
echo ""
echo "////////////////////////////////////////////////////////"
echo "WARNING! : Looks like you have a copy already installed."
echo "////////////////////////////////////////////////////////"
installed_version=$(grep -E "^# version " ~/bin/start-private-browser.bash | tail -n 1 | awk '{print $3}')
echo ""
echo " Installed version : ${installed_version}"
echo " Downloaded version : ${downloaded_version}"
if [[ "${SPB_SKIP_OVERWRITE_CHECK}" != "true" ]] ; then
echo ""
echo " Existing copy path : ~/bin/start-private-browser.bash"
echo ""
echo -n " Should we continue and overwrite the existing copy? [Y/n] : "
read overwrite_existing
if \
[[ "${overwrite_existing}" == "n" ]] || \
[[ "${overwrite_existing}" == "N" ]] || \
[[ "${overwrite_existing}" == "no" ]] || \
[[ "${overwrite_existing}" == "No" ]] || \
[[ "${overwrite_existing}" == "NO" ]] \
; then
echo ""
echo " Understood.. Install aborted. You selected to not overwrite the existing version :"
echo " ~/bin/start-private-browser.bash"
echo ""
# clear EXIT trap and exit (with error) - installation did not complete succesfully.
trap - EXIT ; exit -1
fi
else
echo ""
echo " WARNING! : Enviroment Varable : SPB_SKIP_OVERWRITE_CHECK = true"
echo " WARNING! : Overwriting existing file : ~/bin/start-private-browser.bash"
fi
echo ""
else
echo "Downloaded for installation : SPB version : ${downloaded_version}"
echo ""
fi
# *** TODO *** : put in checking version and then just allow upgrades - that could do with some more work sometime
# copy file start-private-browser.bash into place - assumes you have write access to your home directory.
mkdir -p ~/bin/
if [ -e ~/bin/spb-update.bash ] ; then
# move any old file found to the side for deletion at script run end
mv ~/bin/start-private-browser.bash ~/bin/start-private-browser.bash.old.2delete
fi
cp 050.start-private-browser.bash ~/bin/start-private-browser.bash
chmod +x ~/bin/start-private-browser.bash
spb_upgrade_install_status="success"
echo "File install location : ~/bin/start-private-browser.bash"
echo ""
echo "SPB (Start Private Browser) has been successfully installed!"
echo ""
# copy file spb-update.bash into place - assumes you have write access to your home directory.
mkdir -p ~/bin/
if [ -e ~/bin/spb-update.bash ] ; then
# move any old file found to the side for deletion at script run end
mv ~/bin/spb-update.bash ~/bin/spb-update.bash.old.2delete
fi
cp 600.spb-update.bash ~/bin/spb-update.bash
chmod +x ~/bin/spb-update.bash
spb_update_script_status="success"
echo "File install location : ~/bin/spb-update.bash"
echo ""
echo "SPB (Start Private Browser) update has been successfully installed!"
echo "You may run this script manually or via a schedular to update SPB."
echo ""
# if SPB_CRON_SETUP enviroment variable is set to ture, then we setup the upate crontab
if [[ "${SPB_CRON_SETUP}" == "true" ]] ; then
# run the 700.spb-add-to-user-crontab.bash script to setup the crontab
echo ""
echo "////////////////////////////////////////////////////////"
echo "WARNING! : Enviroment Varable : SPB_CRON_SETUP = true"
echo "////////////////////////////////////////////////////////"
echo ""
echo "Attempting to add entry to update SPB into your users crontab..."
echo ""
if [ -e ./700.spb-add-to-user-crontab.bash ] ; then
chmod +x ./700.spb-add-to-user-crontab.bash
./700.spb-add-to-user-crontab.bash
else
echO ""
echo " ERROR! : SPB User crontab setup requested : Unable to locate the spb-add-to-user-crontab.bash script"
echo ""
exit -101
fi
echo ""
echo " SPB crontab entry set succesfully"
echo ""
echo " SPB (Start Private Browser) will attempt to automatically update,"
echo " when the system is running and there is an active internet connection."
echo ""
echo " SPB crontab entry may be removed or edited using the command 'crontab -e'"
echo ""
fi
# prevent exit if we hit an error and remove the EXIT trap
set +e
trap - EXIT
# configure macOS to not auto delete browser data directories from /tmp/
os_type="$(uname)"
if [[ "${os_type}" == "Darwin" ]] && [[ "${SPB_SKIP_OVERWRITE_CHECK}" != "true" ]] ; then
mod_applied_to_periodic_conf=$(grep "daily_clean_tmps_ignore" /etc/defaults/periodic.conf | grep "browser-" > /dev/null ; echo ${?})
if [[ ${mod_applied_to_periodic_conf} != 0 ]] ; then
# running on macOS
echo ""
echo " SPB specific notes for macOS users :"
echo ""
echo " Some versions of macOS automatically clean-up the /tmp/ directory periodically."
echo " In the event your browser becomes unresponsive then this is likely due to such an automatic"
echo " clean up of the directory."
echo ""
echo " It is possible to work around this issue by adding an additional line to cleanup script."
echo " Making the change to the automated clean up script requires sudo access on the system."
echo " The file to modify is prevents automated clean up of the SPB browser data is : "
echo " /etc/defaults/periodic.conf"
echo ""
echo " Typically, this file contains at least one entry starting with : "
echo " daily_clean_tmps_ignore="
echo ""
echo " To make the alteration manually edit the file : /etc/defaults/periodic.conf "
echo " and locate the last line which states with :"
echo " \"daily_clean_tmps_ignore\""
echo ""
echo " Then, directly below that line add the line below :"
echo " daily_clean_tmps_ignore=\"\$daily_clean_tmps_ignore browser-\""
echo ""
echo " Once this changes is complete, you should no longer have issues with browser unresponsivness"
echo " when the browser is left open for three days or more."
echo ""
echo " If you plan to only use the browser for less than 72 hours, then this alteration is not needed."
echo ""
echo " It is reccomended that you just let this script to make the above "
echo " alteration automatically on your behalf - (this requires sudo access)"
echo " Proceed with automatic edits to the file below : "
echo -n " '/etc/defaults/periodic.conf' file? [y/N] : "
read update_peridic_file
if \
[[ "${update_peridic_file}" == "y" ]] || \
[[ "${update_peridic_file}" == "Y" ]]|| \
[[ "${update_peridic_file}" == "yes" ]] || \
[[ "${update_peridic_file}" == "Yes" ]] || \
[[ "${update_peridic_file}" == "YES" ]] \
; then
if ! [ -f /etc/defaults/periodic.conf ] ; then
echo ""
echo " ERROR : Unable to locate /etc/defaults/periodic.conf"
echo ""
exit -10
fi
grep daily_clean_tmps_ignore /etc/defaults/periodic.conf > /dev/null
if [[ ${?} != 0 ]] ; then
echo "" ; echo " ERROR : origional /tmp/periodic.conf file is missing daily_clean_tmps_ignore variable line(s)" ; echo "" ; exit -8
fi
touch /tmp/periodic.conf
if [[ ${?} != 0 ]] ; then
echo "" ; echo " ERROR : creating tempoary file : /tmp/periodic.conf" ; echo "" ; exit -8
fi
chmod 700 /tmp/periodic.conf
if [[ ${?} != 0 ]] ; then
echo "" ; echo " ERROR : altering file permissions : /tmp/periodic.conf" ; echo "" ; exit -9
fi
awk -v n="daily_clean_tmps_ignore=\"\$daily_clean_tmps_ignore browser-\"" '
/daily_clean_tmps_ignore=/ {l=NR}
{lines[NR]=$0}
END {
for(i=1;i<=NR;i++) {
print lines[i]
if(i==l) print n
}
}
' /etc/defaults/periodic.conf > /tmp/periodic.conf
if [[ ${?} == 0 ]] ; then
echo ""
echo " In order for this script to automatically modify the /etc/defaults/preidic.conf"
echo " file, you will now be prompted for your sudo password."
echo ""
elevate_privildges
# backup the origional file (just in case)
sudo cp /etc/defaults/periodic.conf /etc/defaults/periodic.conf.spb.bak
if [[ ${?} != 0 ]] ; then
echo ""
echo " ERROR : unable to create backup of /etc/defaults/periodic.conf"
echo " sudo authentication failed"
echo ""
exit -10
fi
# using tee instead of cat so
# that we can use sudo for writing the data
# + we will easily be able to show file if needed down the road
sudo tee /etc/defaults/periodic.conf < /tmp/periodic.conf > /dev/null
if [[ ${?} == 0 ]] ; then
rm -rf /tmp/periodic.conf
echo ""
echo " Periodic clean script has been successfully updated."
echo " You are now all set to start use start-private-browser"
echo " with browser sessions which extend beyond a single day."
echo ""
echo " A copy of the origional file has been saved : "
echo " /etc/defaults/periodic.conf.spb.bak"
echo ""
echo " To restore the origional file, run the command : "
echo " sudo cat /etc/defaults/periodic.conf.spb.bak > /etc/defaults/periodic.conf"
echo ""
else
echo ""
echo " ERROR : Unable to update the file : /etc/defaults/periodic.conf"
echo " You could try running the following command manually : "
echo ""
echo " sudo cat /tmp/periodic.conf > /etc/defaults/periodic.conf"
echo ""
fi
fi
else
echo ""
echo " Understood. No changes made to the '/etc/defaults/periodic.conf'"
echo ""
fi
echo ""
fi
fi
# show alias commands (various shells) - if we do some shell detection could run this command automatically.
existing_spb_alias_return_code=$( fish -c ' "alias" | grep -E "^alias spb " > /dev/null ; echo $status ' )
if [[ ${existing_spb_alias_return_code} == 0 ]] ; then
configure_update_spb_fs="update"
else
configure_update_spb_fs="configure"
fi
auto_install_fish_snippits_ask="yes"
if $(which fish >/dev/null) ; then
# if the skipping enviroment varable was set to true, then we will not be asking questions we will just update
if [[ "${SPB_SKIP_OVERWRITE_CHECK}" == "true" ]] ; then
auto_install_fish_snippits_ask="no"
auto_install_fish_snippits="yes"
fi
# no existing spb fish alias configured ; so we ask about setting up the fish snippits automatically
if [[ "${auto_install_fish_snippits_ask}" == "yes" ]] ; then
echo "Detected fish shell : "
echo " You have the fish shell installed, would you like to automatically"
echo -n " ${configure_update_spb_fs} the spb (start-private-browser) fish snippits [Y/n] : "
read auto_install_fish_snippits
if \
[[ "${auto_install_fish_snippits}" == "n" ]] || \
[[ "${auto_install_fish_snippits}" == "N" ]] || \
[[ "${auto_install_fish_snippits}" == "no" ]] || \
[[ "${auto_install_fish_snippits}" == "No" ]] || \
[[ "${auto_install_fish_snippits}" == "NO" ]] \
; then
echo ""
echo " Understood.. automated fish spb snippits setup skipped."
echo ""
else
auto_install_fish_snippits="yes"
fi
fi
if [[ "${auto_install_fish_snippits}" == "yes" ]] ; then
# kick off the automated fish spb snippits installer
/bin/bash -c "$(curl -fsSL https://gist.githubusercontent.com/henri/4f034f04b35c01e089e98350c902bda8/raw/spb-fish-function-installer.bash)"
if [[ $? == 0 ]] ; then
spb_fish_snippits_install_status="success"
else
spb_fish_snippits_install_status="failure"
fi
fi
fi
command_header_printed="false"
function print_command_header {
if [[ "${command_header_printed}" == "false" ]] ; then
echo " Enter the appriate command for your shell(s) to setup alias"
echo ""
command_header_printed="true"
fi
}
if $(which fish >/dev/null) && [[ ! -e ~/.config/fish/functions/start-private-browser.fish ]] ; then
print_command_header
echo " - fish"
echo " alias -s start-private-browser=\"~/bin/start-private-browser.bash\""
echo ""
fi
if $(which fish >/dev/null) && [[ ! -e ~/.config/fish/functions/spb.fish ]] ; then
print_command_header
echo " - fish"
echo " alias -s spb=\"start-private-browser\""
echo ""
echo " If you would like to always have additional parameters passed to start-private-browser command,"
echo " then adding them to the alias 'spb' is a good way to always have them present ; especially when"
echo " using the supplimentary fish functions found at the link below :"
echo " https://gist.github.com/henri/4f034f04b35c01e089e98350c902bda8"
echo ""
fi
if $(which bash >/dev/null) && ! $(grep --silent start-private-browser ~/.bash_alias 2>/dev/null) ; then
print_command_header
echo " - bash"
echo " echo alias start-private-browser=\"~/bin/start-private-browser.bash\" >> ~/.bash_alias && sync && . ~/.bash_alias"
echo ""
fi
if $(which zsh >/dev/null) && $(ps -a | grep --silent zsh) && ! $(grep --silent start-private-browser ~/.zsh_alias 2>/dev/null) ; then
print_command_header
echo " - zsh"
echo " echo alias start-private-browser=\"~/bin/start-private-browser.bash\" >> ~/.zsh_alias && sync && . ~/.zsh_alias"
echo ""
fi
# report summarty reagrding installation of spb and snippits
# this is only displayed if fish snippits optional install was attempted
# the exit values are also pulled for spb update and the fish snippts from this code block
spb_report_summary_header="Installation Summary : "
spb_report_exit_status=0
if [[ "${spb_upgrade_install_status}" == "success" ]] ; then
spb_report_summary="SPB (Start Private Browser) ${spb_upgrade_install} succesfull [ ${tick_mark} ] "
else
spb_report_summary="ERROR! : SPB (Start Private Browser) ${spb_upgrade_install} failed [ X ] "
spb_report_exit_status=99
fi
if [[ "${spb_fish_snippits_install_status}" == "success" ]] ; then
echo "" ; echo "${spb_report_summary_header}"
echo -e "SPB fish snippits ${spb_upgrade_install} completed succesfully [ ${tick_mark} ] "
echo -e "${spb_report_summary}"
elif [[ "${spb_fish_snippits_install_status}" == "failure" ]] ; then
echo "" ; echo "${spb_report_summary_header}"
echo -e "ERROR! : SPB fish snippits ${spb_upgrade_install} failed [ X ]"
echo -e "${spb_report_summary}"
spb_report_exit_status=98
fi
echo ""
# clean up
cd /tmp/ && rm -rf ${temporary_build_directory}
spb_clean_up_exit_status=${?}
# setup traps for exit and cleanup with command to remove old scripts and support files ; idea is to keep any old inodes around as long as possible
if [[ "${SPB_UPDATE_SCRIPT_SKIP}" != "true" ]] ; then
trap 'rm -f ~/bin/start-private-browser.bash.old.2delete ; rm -f ~/bin/spb-update.bash.old.2delete' EXIT
else
trap 'rm -f ~/bin/start-private-browser.bash.old.2delete' EXIT
fi
# confirm we exit with correct overall status from all operations
if [[ ${spb_clean_up_exit_status} == 0 ]] && [[ ${spb_report_exit_status} == 0 ]] ; then
exit 0
else
exit 1
fi
#!/usr/bin/env bash
#
# (C)2025 Henri Shustak
# SPB Update Script
# This script will pull down and update
# the SPB project and fish snippits
#
# The intention of this script is that it is called via cron, launchd
# or some other mechanisim to automate the upgrade process.
#
# This script is part of the spb project :
# https://gist.github.com/henri/34f5452525ddc3727bb66729114ca8b4/
#
# Licenced Under the GNU GPL v3 or later
# https://www.gnu.org/licenses/gpl-3.0.en.html
#
# version 1.0 - initial release (basic logging to home directory)
# version 1.1 - added support for interactive tty detection
# version 1.2 - bug fixes
# version 1.3 - added a bypass parameter for the random delay
# version 1.4 - added support for starting an auto update and being able to monitor the log with tail
# version 1.5 - added additional information relating to log monitoring
# version 1.6 - added a usage page accessable via the --help flag
# version 1.7 - bug fixes
# version 1.8 - implimented timeout features (sometimes only if coreutils has been installed on system)
# version 1.9 - further improvments related to --no-delay option when used in conjunction with --auto-monitoring
# version 2.0 - minor help output information improvements
# version 2.1 - attempts to keep scroll back when viewing the log file with tail
#
# check if we are running with a connected tty for input
# to run this script in auto-mode, use the command below :
#
# ~/bin/spb-update.bash < /dev/null
#
# run automated session answering defaults automatically
# and monitor output via tail - similar to the above but
# adds monitoring (look at function below for details) :
#
# ~/bin/spb-update.bash --auto-monitoring
#
# lock file (one update at a time please)
lock_file="/tmp/spb-update-$(hostname)-$(whoami).lock"
if [ -e ${lock_file} ] ; then
echo "ERROR! : Lock file detected.. update aborted! "
echo " ${lock_file}"
exit -78
fi
touch ${lock_file} # create the lock file :)
# set an EXIT trap (basic to cover the lock file)
trap 'clean_exit' EXIT
# setup a clean exit strategy
exit_status=0
# setup tail runtime timeout value for --auto-monitoring option
which timeout >> /dev/null ; timeout_available=${?}
if [[ ${timeout_available} == 0 ]] ; then
timeout_available="true"
else
timeout_available="false"
fi
tail_runtime_timeout=15 # how long to wait when running tail
auto_update_proceed_timeout=60 # when you are asked a question
# this will tidy up the lock file if we exit
function clean_exit () {
rm -f ${lock_file} > /dev/null
if [[ ${exit_status} == 0 ]] ; then
# disable the exit trap
trap - EXIT
fi
# remove any old update scripts
rm -f ~/bin/spb-update.bash.old.2delete
exit ${exit_status}
}
function update_auto_answer () {
echo ""
echo "Starting SPB update process :" ; echo ""
echo " This update system is about to start in a non-interactive mode."
echo " During the SPB update the log will be displayed on screen." ; echo ""
echo " All options will be automatcially answered using DEFAULT options."
echo ""
sleep 0.5
# provide an option to bottle out - unless --no-delay option was specified in addition to --auto-monitoring option
if [[ "${auto_monitoring_start_delay}" == "yes" ]] ; then
echo " Automatically continuing in ${auto_update_proceed_timeout} seconds..."
echo -n " Do you wish to continue now? [Y/n] : "
read -t ${auto_update_proceed_timeout} auto_update_proceed
if \
[[ "${auto_update_proceed}" == "n" ]] || \
[[ "${auto_update_proceed}" == "N" ]] || \
[[ "${auto_update_proceed}" == "no" ]] || \
[[ "${auto_update_proceed}" == "No" ]] || \
[[ "${auto_update_proceed}" == "NO" ]] \
; then
echo ""
echo " Understood.. Update aborted."
echo ""
exit_status=0
clean_exit
fi
fi
sleep 1
echo "" ; echo ""
echo "Starting up SPB update log monitoring system..."
echo ""
sleep 2
# this could be more fancy and monitor the screen session / get the tail PID and auto kill but no we are not doing that.
rm -f ${lock_file} # remove the lock
# configure time out settings if it is available on this system
timeout_command=""
if [[ "${timeout_available}" == "true" ]] ; then
timeout_command="timeout --foreground ${tail_runtime_timeout}s"
fi
# start a screen session and recursivily call this script, set enviroment varable to report how to exit tail and start the update monitoing with tail command to monintor the log file
screen -dm -S "spb-update" bash -c "export SPB_UPDATE_AUTO_ANSWER=\"true\" ; sleep 1 ; ~/bin/spb-update.bash --no-delay </dev/null" && clear -x ; sleep 1; ${timeout_command} tail -n0 -f ~/bin/spb-update.log
# exit as we have completed the run, no clean exit call as this will have been handled by the recursive call
exit 0
}
# let the install script know that it was started via the update script
export SPB_UPDATE_SCRIPT_SKIP="true"
# if this variable is passed into the script then we will add a line explaining how to exit from tail at the end of the output
if [[ "${SPB_UPDATE_AUTO_ANSWER}" != "true" ]] ; then
# SPB_UPDATE_SCRIPT_SKIP should be set to ture, if this script is launced via the update script
SPB_UPDATE_AUTO_ANSWER="false"
fi
# parse arguments / parameters / options etc...
update_delay="yes"
auto_monitoring_start_delay="yes"
auto_monitoring="no"
for arg in "${@}"; do
if [[ "${arg}" == "--help" ]] || [[ "${arg}" == "-h" ]] ; then
if [ -t 0 ] ; then # we are running interactivly
echo "" ; echo ""
echo " This script is part of the SPB (start-private-browser) project :"
echo " - https://gist.github.com/henri/34f5452525ddc3727bb66729114ca8b4/" ; echo "" ; echo ""
echo " Usage : " ; echo ""
echo " # Show this help message" ; echo ""
echo " ~/bin/spb-update.bash --help" ; echo "" ; echo ""
echo " # Disable the random delay when running"
echo " # without a tty connected to stdin" ; echo ""
echo " ~/bin/spb-update.bash --no-delay" ; echo "" ; echo ""
echo " # Run the script without a tty connected to stdin."
echo " # This will have the result of this script using"
echo " # default options rather than providing interactive"
echo " # prompts. Use this to simulate what will happen"
echo " # when run via a scuduling system such as cron" ; echo ""
echo " ~/bin/spb-update.bash </dev/null" ; echo "" ; echo ""
echo " # Use when a tty is connected, but you would"
echo " # like the script to behave like no tty is"
echo " # connected. This ensures automatic selection"
echo " # of default options. In addition, this option"
echo " # will tail the ~/bin/spb-update.log file"
echo " # Finally it will also enable the --no-delay"
echo " # option behaviour specified above automatically"
echo " # on your behalf" ; echo ""
echo " ~/bin/spb-update.bash --auto-monitoring" ; echo ""
echo " # Again when tty is connected ; if the --no-delay"
echo " # option is used in combination with the"
echo " # --auto-monitoring option, then the"
echo " # regular --no-delay behaivour is included, and"
echo " # in adition, no pre-flight delay will be offered"
echo " # in which you would normally be able to"
echo " # change your mind to abort (caution)" ; echo ""
echo " ~/bin/spb-update.bash --auto-monitoring --no-delay" ; echo "" ; echo ""
clean_exit
fi
fi
done
# one loop for each argument we are checking # not doing them together on purposes
# this argument is deliberatly checked after the --help argument
for arg in "${@}"; do
# are we going to have a delay before we run the unattended update
if [[ "${arg}" == "--no-delay" ]]; then
update_delay="no"
auto_monitoring_start_delay="no"
fi
done
# one loop for each argument we are checking # not doing them together on purposes
# this argument is deliberatly checked after the --no-delay argument
for arg in "${@}"; do
# are we going to run unattneded but monitor things
if [[ "${arg}" == "--auto-monitoring" ]]; then
auto_monitoring="yes"
# recurssivly kick off this script in a screen session and monitor the logs with tail
update_auto_answer
fi
done
# set an EXIT trap
trap 'echo "" ; echo "Something went horribly wrong with the update script, please try again later!" ; echo "" ; exit_status=55 ; clean_exit' EXIT
if [ -t 0 ] && [[ "${SPB_UPDATE_AUTO_ANSWER}" != "true" ]] ; then
echo "Interactive TTY detected. Running interactive update..."
# update SPB
/bin/bash -c "$(curl -fsSL \
https://gist.githubusercontent.com/henri/\
34f5452525ddc3727bb66729114ca8b4/raw/\
500.spb-install-script.bash)"
exit_status=${?}
clean_exit
fi
# just update things do not ask to overwrite files (danger will robbinson)
# we set this after we have gone past the interactive section so that we
# now have auto-updates (default answer automatically) enabled.
export SPB_SKIP_OVERWRITE_CHECK="true"
# set an EXIT trap with logging to file
trap 'echo "Something went horribly wrong with the unattended update script, please try again later!" >> ${log_file} ; exit_status=55 ; clean_exit' EXIT
# preform exit if we hit an error
set -e
# logging file (for now)...
log_file="$HOME/bin/spb-update.log"
log_file_temporary="$HOME/bin/spb-update.log.tmp"
log_file_truncated="no"
# check the log file size.
if [[ -e ${log_file} ]] ; then
if [[ $(du ${log_file} 2> /dev/null| awk '{print $1}') -ge 1000 ]] ; then
# log is getting large, cut it down to size (trim down to around 500kilobytes and then start with the first entry)
tail -c 500k ${log_file} | sed '1,/^------------------------------------------------------------------------$/d' > ${log_file_temporary}
mv ${log_file_temporary} ${log_file}
log_file_truncated="yes"
fi
fi
# prevent exit if we hit an error and remove the EXIT trap
set +e
# only report success if we actually have success
update_exit_status=10
# report we are starting an update
echo "" >> ${log_file}
# carful the length of this next line is important for trimming the file when it is too large
echo "------------------------------------------------------------------------" >> ${log_file}
echo "SPB auto update starting up..." >> ${log_file}
echo "$(date)" >> ${log_file}
if [[ "${log_file_truncated}" == "yes" ]] ; then
echo "FYI : Log file has been truncated to save space. The oldest data is no longer available." >> ${log_file}
fi
echo "Running in non-interactive mode..." >> ${log_file}
if [[ "${update_delay}" == "yes" ]] ; then
random_update_delay=$(max_random=80 ; ((random_value=$RANDOM%$max_random)) ; echo $random_value)
echo "Random update delay ${random_update_delay} (seconds)... " >> ${log_file}
sleep ${random_update_delay}
else
echo "Random update delay... [skipped] " >> ${log_file}
fi
echo "SPB auto update running..." >> ${log_file}
echo "$(date)" >> ${log_file}
start_epoch="$(date +%s)"
# check the update script is accessable
script_accessable=$(curl -fsSL \
-o /dev/null -w "%{http_code}" \
https://gist.githubusercontent.com/henri/\
34f5452525ddc3727bb66729114ca8b4/raw/\
500.spb-install-script.bash 2> /dev/null)
# convert a 200 code into a 0 code.
if [[ ${script_accessable} == 200 ]] ; then script_accessable=0 ; fi
# not a perfect check this could be improved...
if [[ ${script_accessable} == 0 ]] ; then
# update SPB
/bin/bash -c "$(curl -fsSL \
https://gist.githubusercontent.com/henri/\
34f5452525ddc3727bb66729114ca8b4/raw/\
500.spb-install-script.bash)" 2>&1 >> ${log_file}
update_exit_status=${PIPESTATUS[0]}
exit_status=${update_exit_status}
fi
end_epoch="$(date +%s)"
total_run_time=$(( end_epoch - start_epoch))
# report total run time
echo "$(date)" >> ${log_file}
echo "Total Update Execution Time (in seconds) : ${total_run_time}" >> ${log_file}
# report outcome of update
if [[ ${update_exit_status} == 0 ]] ; then
echo "SPB Update Completed." >> ${log_file}
else
if [[ ${script_accessable} == 0 ]] ; then
echo "ERROR! : Internal update script failed!" >> ${log_file}
else
echo "ERROR! : Unable to access the remote SPB update script!" >> ${log_file}
fi
echo "SPB Update Failed." >> ${log_file}
exit_status=19
fi
if [[ "${SPB_UPDATE_AUTO_ANSWER}" == "true" ]] ; then
echo "" >> ${log_file}
echo "Script initiated with \"--auto-monitoring\" parameter." >> ${log_file}
echo "The above data has been read from : ~/bin/spb-update.log" >> ${log_file}
if [[ "${timeout_available}" == "true" ]] ; then
echo "Auto exit in ${tail_runtime_timeout}s" >> ${log_file}
fi
echo "Press 'control-c' to exit now." >> ${log_file}
fi
# exit with the exit values from the update
clean_exit
#!/usr/bin/env bash
#
# (C)2025 Henri Shustak
# Script will add the ~/bin/spb-update.bash script into the
# users crontab if it is not already present.
#
# This script is part of the spb project :
# https://gist.github.com/henri/34f5452525ddc3727bb66729114ca8b4/
#
# Licenced Under the GNU GPL v3 or later
# https://www.gnu.org/licenses/gpl-3.0.en.html
#
# Note that this script currently adds the entry to the users crontab
# The output fromat of the inserted entry may not match the formatting of existing crontab entries
#
# version 1.0 - inital release
# version 1.1 - bug fixes
#
# configuration
spb_update_script_home_realitive="bin/spb-update.bash"
spb_update_script="$HOME/${spb_update_script_home_realitive}"
crontab_entry="0 3 * * 2\t\t~/${spb_update_script_home_realitive}" # use echo -e to get the tab printing correctly
backup_crontab_entry="/tmp/crontab_backup_$(whoami)"
# variables
exit_status=0
function clean_exit () {
rm -f ${backup_crontab_entry} >> /dev/null
exit ${exit_status}
}
# create the crontab backup file and set permissions so only we can access the file.
touch ${backup_crontab_entry}
chmod 700 ${backup_crontab_entry}
# check if the script is executable and accessable
if ! [ -x "${spb_update_script}" ] ; then
if ! [ -e "${spb_update_script}" ] ; then
echo "ERROR! : The SPB update script is not executable : ${spb_update_script}"
exit_status=8 ; clean_exit
else
echo "ERROR! : Unable to loate the SPB update script : ${spb_update_script}"
exit_status=9 ; clean_exit
fi
fi
# scan the users crontab to see if it is loaded (maybe in the future we will have different options)
crontab -l 2>/dev/null | grep -q "${spb_update_script}"
if [[ ${?} == 0 ]] ; then
echo "SPB Update script is already laoded into the crontab"
clean_exit
fi
# backup the users crontab
crontab -l > "${backup_crontab_entry}"
# install the spb-update.bash script into the crontab
crontab - <<< $(crontab -l 2>/dev/null | grep -v "~/${spb_update_script_home_realitive}" ; echo -e "${crontab_entry}" )
# cat <<< $(crontab -l 2>/dev/null | grep -v "${spb_update_script}" ; echo "" )
cront_tab_modifiaction_exit_value=${?}
# report the situation
if [[ "${cront_tab_modifiaction_exit_value}" == 0 ]] ; then
echo " SPB update script has been added to your crontab."
echo " Show your crontab entires with the command : crontab -l "
clean_exit
else
echo "ERROR! : While attempting to add the SPB update script to your crontab."
echo " You should check your crontab is okay"
echo ""
echo " A backup of your crontab was made before we tried to edit your crontab"
echo " ${backup_crontab_entry}"
echo ""
echo " Check the crontab backup with the command : "
echo " cat ${backup_crontab_entry}"
echo ""
echo " If the backup looks okay, you will be able to restore your crontab to formal glory with : "
echo " cat ${backup_crontab_entry} | crontab -"
echo ""
echo " Finally, confirm your crontab has been restored with : "
echo " crontab -l "
echo ""
exit -99 # exit but leave the crontab backup file
fi

RoadMap

  • More testing
  • Additional documentation.
  • Refactoring to make support for different browsers easier to impliment
  • If we stick to writing files to disk - maybe look at using srm to securly remove files after the sesssion has ended.
  • If this project grows, it may get shifted to a regular github repository to make pulls, issue reporting etc easier.
  • Have an option to start a non-private browser window DONE!
  • Ask if you want to auto-update spb via cron (or some other meathod).
    • Cron is probably the most cross platform appraoch and is all configurable within user-space.
    • Consider detecting tty and exiting with error if the tty is not interactive and the SPB_SKIP_OVERWRITE_CHECK varible not set

Template User Settings

  • Setup a system which allows a directory of templates to be used DONE!
    • Such a templating system would allow customised settings to be enabled when starting an spb instance
    • A templating system would also allow for pre-configured (and bundled within SPB) configurations to be hardended and ready for use by people who are seeking an out of the box set of tempalte setting options.

SandBoxing

  • FileSystem User NameSpaces
    • Restricting Access (eg FireJail etc..) Detroyed on exit.

Possible Features

  • An option to store the directory in memory rather than on disk at all?
  • An option to disable cache being written to disk :
    • --disk-cache-dir=
    • --disk-cache-dir="$XDG_RUNTIME_DIR/this-instance-cache"
    • --disable-application-cache --media-cache-size=1 --disk-cache-size=1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment