The switch to ZSH
ZSH is an alternative to shells like sh, bash or fish. I have nothing against any of them but I choose to use ZSH. There are hundreds of articles that cover the benefits, but very few that I have found also cover the downsides. In this blog, I will discuss some of the reasons I use ZSH and some of the annoyances I face. I work as a penetration tester, so some of the annoyances are specific to that. I am not going to pretend that this is a comprehensive list, it is the things that made my decision.
To start with, I’ll talk about some of the features that make my life easier, the pros. It should come as no surprise that, as I use ZSH on a daily basis, the pros outway the cons for me; that is not to say however that I think zsh is perfect. It isn’t.
PRO: Bash Familiarity
ZSH is not strictly compatible with all BASH or SH features, (more on that later) but it is a lot more similar than some alternative shells. For me, this is important because I spend a lot of time SSHed into machines that have BASH or SH installed. It is often not possible for me to install ZSH so having a similar working environment is hugely beneficial.
PRO: Tab Completion
The tab completion on ZSH is hugely superior to that of bash. As well as giving descriptions of arguments, you can use the tab or arrow keys to cycle through each option
Obviously, the tab completion is better with some tools than others, but zsh is able to fall back to the completion you would get in bash, with the bonus of being able to cycle through options.
PRO: Syntax Highlighting
We all use syntax highlighting in our code editors, why not also have
it in our shell? You can see from the screenshot below that as soon as a
valid command is input, you get feedback by it turning green. If an
invalid command is input, it is red. It saves a lot of the embarrassing
typos where you type gti
instead of git
, or
sl
instead of ls
.
It should be noted that this isn’t a native ZSH feature, but a plugin.
PRO: Autosuggest
Another plugin is the autosuggestion plugin, it adds the last command from your history that matches what you have already typed. You can then use the right arrow key to accept the suggestion. This makes writing long but common commands much quicker.
PRO and CON: ZLE
Zsh uses a tool called zle (zsh line editor) as an alternative to
readline that most other shells use. Readline is also the tool used by
the read
command that many shell scripts use for getting
user input.
ZLE is, subjectively, much more advanced than readline. Personally, my favourite feature is its superior vim emulation, meaning I can edit the command I am currently writing with the same keys I use to edit almost everything else I write (including this blog).
Hoverer, coming to my first annoyance, as it doesn’t use readline,
your readline configuration isn’t read. This makes sense but readline is
everywhere. Metasploit, pappy and bash all use readline as their line
editor. You can configure them all in one place: .inputrc
,
that is all of them except zsh/zle.
That is not to say that you cannot configure zle to do the same things, you absolutely can, but it means making those configuration changes in multiple places.
CON: /dev/tcp (or lack thereof)
/dev/tcp/*
is a non-standard feature that bash added.
ZSH, does not implement this. There is a tool called ztcp
which, like zle, is more powerful than the bash alternative but, in my
opinion, not as easy.
That being said, I only really use that feature when I don’t have netcat available, that is when I am on a remote machine. When that is the case, I am normally in a bash environment anyway.
CON: stty raw -echo
When you get a netcat reverse shell, one of the first things you want
to do is upgrade it to a fully interactive shell. When using Bash, you
would do this by pressing Ctrl+z to background the current process, then
typing stty raw -echo
then typing fg
and
pushing enter twice.
If you try this in ZSH, it won’t work. Why? Because ZSH’s
implementation resets the -echo
option every time the
prompt is drawn. If you’re interested in why, it is discussed here. But,
what that means, is we need to foreground the shell, before the prompt
is drawn. The solution:
stty raw -echo; fg <enter><enter>