BashMe is a framework for Bash startup script generation.
Bash is an extremely powerful and extremely complicated tool at the same time.
Without a proper setup, it is hard to use.
There are a lot of shell options that are not enabled by default, but in fact, they should be.
You just have to figure out for yourself that they exist and learn how to use them.
Also, there are many tools that extend Bash, making it smarter and more informative.
And of course, some of the CLI programs that you install require additional configuration to be added to your shell, like environment variables, so that they can be properly used—especially if you install them manually or with a provided installation script into $HOME,/opt or /usr/local, without a package manager that can do the dirty work for you.
All of that requires you to edit these two Bash startup scripts: .bashrc and .bash_profile.
The more tools you use, the more these startup scripts grow and become harder to deal with. They just aren't designed to be modular; it's up to you to make them so, if you wish. And you certainly do. Because if you use different environments (or workspaces, devices, as you please), you want to share your common startup code between them and separate it from the code that is unique to a specific environment or kind of environment.
You may split startup script functionality into multiple files and source them. But you won't get rid of the feeling that you're doing a job someone else already did. It is so. I recommend at least these wonderful projects:
Then why does BashMe exist?
Well, I personally don't really like the idea of making a whole framework out of a startup script. Your configuration is no longer garbage, that's right. But your device cannot agree with you. There is so much redundant code running again and again every time you start a new Bash session. For most users, this isn't a problem at all. What can I say? We are stuck in a world of abstraction layers and are used to paying a cost for every one of them. But I still prefer to keep things simple and easily controlled, if possible.
And that's when BashMe joins the game. It takes a different approach. Instead of being a framework inside a startup script, it becomes a framework to generate one. BashMe implements a simple, reliable idea: let's write Bash scripts that generate Bash scripts.
The BashMe scripts can figure out what environment you have and what tools you use, and then generate the startup scripts that suit you best. You are free to write your own scripts for your needs because they are basically the same Bash scripts with some predefined functions.
The result is startup scripts that contain nothing redundant. Also, they can optionally be minified and obfuscated.
The big disadvantage is that when you change a part of your environment that affects your startup scripts, or you change your BashMe scripts, you have to regenerate the startup scripts manually. But that may also be an advantage, at least from a security point of view.
Also, BashMe could be better for Bash beginners because it doesn't require you to edit any Bash scripts at all. It already provides useful defaults to start using Bash.
BashMe preserves the complete flexibility of pure Bash while introducing a new way to manage it.
- Bash 5.0 or higher.
- setsid (preinstalled on most Linux distributions).
- shfmt (optional, but highly recommended, because it can be used to minify the startup scripts).
To generate ~/.bash_profile and ~/.bashrc using the standard BashMe scripts only:
bashme --type profile
bashme --type rcIt's also recommended to use at least the --minify option to minify the resulting startup scripts.
Once you have generated them, you can always run bashmeup inside a Bash session to regenerate them.
See bashme --help for more.
BashMe can be used without installation—just clone this repository and run ./bashme.
But for simplicity, to make completions available, and for security reasons, it is recommended to install BashMe at the system level. Use ./install for that. Use ./uninstall to uninstall it.
The standard BashMe scripts provide:
- better Bash defaults (taken from Sensible Bash);
- well-known aliases for Coreutils.
Besides that, they support the tools listed below:
As you can see, that's just a setup for my daily routine and may hardly suit you as is. So, proposals are highly welcome.
You can start by writing your personal BashMe scripts and using them like this:
bashme --type profile ~/.profile.bashme
bashme --type rc ~/.rc.bashmeLook at the scripts inside ./std as an example.
In a BashMe script, there are two functions available: bashme_print and bashme_import.
bashme_print adds code to the generated startup script.
The code can be passed as an argument or as input.
The --later option specifies that the code should be run later than other code.
The -i option specifies that the code should be run only in interactive mode.
This code always runs later.
The resulting order of the code:
- code without options;
- code with the
--lateroption; - code with the
-ioption; - code with both
-iand--lateroptions.
bashme_import imports a new BashMe script to run.
With the help of this function, you can group BashMe scripts into modules or even into module graphs.
Bash scripts may be vulnerable to intruder attacks, as malicious code can easily be written into a script.
So, if you keep BashMe on your system, always install it with root or a separate user, providing read-only access for other users.
Even though .bash_profile and .bashrc are located in the user's home directory, they should also be owned by root or a separate user, with read-only access for other users.
Additionally, you can obfuscate your startup scripts using the --obfuscate option.
This makes it harder for programs to read and analyze the content, making any unexpected code injection easier to detect.
While BashMe itself tries to be simple and widely usable, it also takes several measures to ensure greater security:
- BashMe runs scripts without providing them with
stdinor atty. This means that normally, a script cannot usesu/sudo/etc. to elevate its privileges. - Every script runs in a subshell, so separate scripts cannot affect each other with their variables, functions, etc.