Skip to content

Instantly share code, notes, and snippets.

@StefanFabian
Last active February 9, 2023 14:52
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save StefanFabian/cfc3408f4fc1bb302438a10064c21d9a to your computer and use it in GitHub Desktop.
Save StefanFabian/cfc3408f4fc1bb302438a10064c21d9a to your computer and use it in GitHub Desktop.
MultiEnv: A small bash tool to handle multiple (possibly) clashing bash environments, e.g., different ROS workspaces
#!/bin/bash
# ___ ___ _ _ _ _____ _ ____ __ _ __ __
# | \/ | | | | | | | |_ _| | | | __| | \ | | \ \ / /
# | |\ /| | | |_| | | |__ | | | | | |__ | \ | | \ \ / /
# |_| \/ |_| |_____| |____| |_| |_| | __| | |\ \| | \ \/ /
# | |__ | | \ | \ /
# v1.0 by Stefan Fabian |____| |_| \__| \/
#
# This script installs multienv, a small bash tool that allows you to easily switch between environments.
# For available commands run 'multienv help' after installation.
# Tab-completion is also supported!
#
# For example, let's say you have an environment using a catkin workspace overlaying the
# ROS (Robot Operation System) software stack.
# You would create an env named my_workspace:
# multienv create my_workspace
#
# This would open up an editor with a shebang line already filled in, you would modify it to contain:
# #!/bin/bash
# source /home/user/workspace_path/devel/setup.bash
#
# Save the file and exit. Now, you've created an environment.
# To switch to it, run:
# multienv switch my_workspace
#
# This will start a new shell session and source the script you created above.
# You do some work in that environment and after you're done, you want to switch the environment off again.
# For that, there's the special 'none' environment.
# multienv switch none
#
# This will start a new shell session and not source anything.
# Alternatively, you could also switch to a different environment (after you created more than one).
# A new terminal will always start with the session that was last switched to.
# To switch only your currently active terminal use the --this option.
#
# =========
# CHANGELOG
# =========
# v1.0:
# - Added reload command
# - Fixed env switch changing directory to the user's home directory
#
MULTIENV_INSTALL_DIR=~/.multienv
NC='\033[0m'
RED='\033[0;31m'
GREEN='\033[0;32m'
BROWN='\033[0;33m'
BLUE='\033[0;34m'
function info() {
echo -e "${BLUE}${1}${NC}"
}
function warn() {
echo -e "${BROWN}${1}${NC}"
}
function success() {
echo -e "${GREEN}${1}${NC}"
}
function error() {
echo -e "${RED}${1}${NC}"
}
if [[ -d $MULTIENV_INSTALL_DIR ]]; then
echo "It looks like multienv is already installed!"
read -p "Proceed anyway? (Y/n): " MULTIENV_INSTALL_PROCEED
if [[ $MULTIENV_INSTALL_PROCEED != "Y" && $MULTIENV_INSTALL_PROCEED != "y" ]]; then
exit 0
fi
fi
echo -e "\e[31m ___ ___ \e[33m _ _ \e[32m _ \e[36m _____ \e[34m _ \e[0m ____ __ _ __ __"
echo -e "\e[31m| \/ | \e[33m| | | | \e[32m| | \e[36m|_ _| \e[34m| | \e[0m| __| | \ | | \ \ / /"
echo -e "\e[31m| |\ /| | \e[33m| |_| | \e[32m| |__ \e[36m | | \e[34m| | \e[0m| |__ | \ | | \ \ / / "
echo -e "\e[31m|_| \/ |_| \e[33m|_____| \e[32m|____|\e[36m |_| \e[34m|_| \e[0m| __| | |\ \| | \ \/ / "
echo " | |__ | | \ | \ / "
echo "v1.0 by Stefan Fabian |____| |_| \__| \/ "
echo
info "> Creating directory"
mkdir -p $MULTIENV_INSTALL_DIR/envs
info "> Configuration"
echo "Would you like to enable write protection?"
echo "Write protection requires sudo privileges to create, edit, delete environments as the relevant files will be write protected from normal users to prevent malicious modification."
read -p "Enable? (Y/n): " MULTIENV_INSTALL_WRITE_PROTECTION
if [[ $MULTIENV_INSTALL_WRITE_PROTECTION == "y" || $MULTIENV_INSTALL_WRITE_PROTECTION == "Y" ]]; then
success "Write protection enabled!"
else
echo -e "Write protection ${RED}not${NC} enabled."
fi
info "> Unzipping content"
if [ -f $MULTIENV_INSTALL_DIR/multienv.sh ] && [ ! -w $MULTIENV_INSTALL_DIR/multienv.sh ]; then
warn "Looks like you're reinstalling and write protection is enabled."
warn "Removing write protection (temporarily unless not enabled this time) for update."
sudo chattr -i $MULTIENV_INSTALL_DIR/multienv.sh
fi
echo "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" | base64 -d | gzip -d > $MULTIENV_INSTALL_DIR/multienv.sh
if [ $? -ne 0 ]; then
error "An error occured while unzipping!"
exit 1
else
success "Unzipped $MULTIENV_INSTALL_DIR/multienv.sh"
fi
if [[ $MULTIENV_INSTALL_WRITE_PROTECTION == "y" || $MULTIENV_INSTALL_WRITE_PROTECTION == "Y" ]]; then
sudo chattr +i $MULTIENV_INSTALL_DIR/multienv.sh
sudo chmod 555 $MULTIENV_INSTALL_DIR/envs
fi
info "> Append to .bashrc"
MULTIENV_SOURCE_COMMAND="source $MULTIENV_INSTALL_DIR/multienv.sh"
if [ ! -w ~/.bashrc ]; then
error "Your .bashrc seems to be write protected. Good for security!"
echo "However, that means you will have to add the following yourself:"
echo "source $MULTIENV_INSTALL_DIR/multienv.sh"
exit 0
fi
# Remove old source if exists
sed -i -z "s/$(echo -ne $MULTIENV_SOURCE_COMMAND | sed 's,/,\\/,g' | tr '\n' '^' | sed 's/\^/\\n/g')//g" ~/.bashrc
echo $MULTIENV_SOURCE_COMMAND >> ~/.bashrc
success "All done."
@StefanFabian
Copy link
Author

MultiEnv is a small bash tool that enables the separation of different console environments with minimal footprint.
You can create environments that consist of a few lines of bash that are sourced whenever the environment is loaded.
Switching environments is persistent between terminal sessions which means if you switch the environment and open a new terminal, the new terminal will also use the environment you switched to.

Use cases for this tool include the separation of different ROS or ROS 1 and ROS 2 workspaces.
Switching the environment will produce a clean bash where the other environment was never sourced. Bash history is preserved.

Changelog v0.9:

Added --this option for multienv switch ENV_NAME to switch only active terminal.
Fixed some security flaws that would have allowed to inject code to be run when multienv is sourced.

@StefanFabian
Copy link
Author

Update v1.0

  • Added reload command that will reload the active environment and reset the environment.
  • Fixed environment switch or reload resulting in a change of the current working directory back to the users home directory

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