Well, I use terminals for nearly everything but a few things like image editing.
I'd like to share my reasons for doing so, focusing on user experience.
the shell is a language for program composition
Terminals (and shells) are what allow me to have a conversation with my
computer. I don't use the terminal to do things; I use it to communicate my
intent to the system and have it do it for me.
For example, with a shell I can do incrementally more complex tasks. Anything I
can do by hand, I can tell the system to do it itself.
# report status of service
systemctl status mariadb
# do it on foo.com
ssh foo.com "systemctl status mariadb"
# do it for bar-1.foo.com through bar-8.foo.com
for i in {1..8}; do ssh bar-$i.foo.com "systemctl status mariadb"; done
Please note that these three commands in turn require no retyping of anything if
you know either the shell keybindings for history navigation and command line
editing, history expansion, or even copying and pasting. The result of each
command will be in the terminal for easy reviewing and comparison. Absolutely
everything can be copied and pasted to anywhere in the system.
The equivalent of the last command with a gui would require me to login to each
system through some remote desktop protocol and manually check the status of
each service by moving a mouse around and clicking icons, sending mouse
coordinates and clicks and receiving a video feed containing a wallpaper and
windows and menus popping up. There is going to be no simple way to compare the
results side by side. I'd need the protocol to either handle shared clipboards
and copy the results to a file in my local computer, or handle that many
heavyweight connections and resize the windows to hide the wallpapers and stuff.
Ok, now I want to be emailed if one of them goes down.
while true; do
for i in {1..8}; do
echo "==> bar-$i.foo.com"
ssh bar-$i.foo.com "systemctl status mariadb"
done > /tmp/services.txt
if grep '^\s*Active:' /tmp/services.txt | grep -qv running; then
mail -s "service failed!" [email protected] < /tmp/services.txt
fi
sleep 10m
done &
Simple enough. Now, because I've no clue on how to extract information out of a rendered gui (OCR?), I can't do the equivalent with gui's.
The problem I'm trying to get at with the gui way is that I have no way to tell
the system things like for i in {1..8}
or if grep ...
with the gui, and it's
really cumbersome to tell it "move the mouse to this coordinate, double click,
and wait this estimated amount of time before clicking in this new window...",
and that's assuming I can guess where the new window will appear...
I can do things with the gui, but it's not a language. I can't tell it what I
want done so it can do it for me. I must do it myself.
easy to communicate
How would you give instructions to do a specific task to other people? In a gui
you'd have to tell them to click on the fox, then the hamburger (if they
understand that term), menu, menu, menu, tab, click, exit, click, etc. Sometimes
it helps to post screenshots of the gui with big red arrows pointing at where
they need to go.
With commands, you just... write them. If the actions are too complex and they
trust you, they can just copy and paste the commands and be done with it.
storable actions
This might be obvious, but you can combine a complex set of commands, put them
in a file and run it... it's pure automation; how can a gui compete with that?
shell keybindings, globbing, brace expansion, history expansion, etc.
I think most people that complain about the shell, do it because they end up
typing very repetitively (it might also be because it still requires a lot more
typing, though I'd argue that that's a plus).
The shell has many features that make working with it extremely efficient. The
catch is that you must learn about those features. It's all in man bash
and
man zshall
. It's too much to even scratch the surface here.
Well, the point here is that the shell provides many facilities to cut out the
repetition in your work. Gui's of specific programs might something similar
through history functionality and the like, but the shell works for practically
everything.
terminal scrollback-buffer and shell history
I got my terminal configured to save the last 100000 lines for display. If I
leave my computer for a while or don't revisit a terminal in some time, I can
always scroll back and see what I've done involving any (terminal) program. I
got my shell prompt setup to display a timestamp before and after I run a
command. I can always tell how long a command ran without preemptively running
it with time
. It's so simple, but how would you do that with a gui? Implement
some kind of video playback for the desktop to always be recording?
I also have the shell to save the last 2000000 commands in a history file. If I
look at the file, not only does it have the commands, each one has a timestamp
of when I ran it. Some months ago, my boss asked me to do some task I did a few
months after being hired. I can't remember now but I remember I couldn't
remember then. It was multiple complex commands involving some set of servers.
Thankfully, I still held the commands in the history file. It was so insanely
easy to just find them and re-run them. I was so impressed, I increased my
history size limit by two-orders of magnitude. What would you do in this
situation if everything you do was with a gui?
simpler to program
Programmers are also users. The ease to write terminal programs is also part of
the user experience, and it most certainly is a reason why so many new programs
are written to work for a terminal.
You don't have to deal with creating windows and widgets, and some rendering
loop. You just get your arguments from an array and print some text to standard
output.
Programming for a terminal instead of a gui also has another implication: text
configuration files meant to be edited by hand. When was the last time you used
a gui program and was expected to configure it by opening a file, editing it and
then restarting a program? A user of a gui program expects to be able to
configure it through the gui.
For the programmer, this means that not only does he have to write and read the
configuration in files, but he must also implement widgets for it.
As the programmer will expect the user to use the widgets, editing the
configuration file by hand is probably going to be a suboptimal experience. For
the user, this also has downsides:
- he won't be easily able to share the configuration with other computers and friends.
- he won't be able to put comments on it as they'll be overwritten.
- it might be problematic to track changes in version control.
single input and output
When I'm having trouble with some program and the error message is not too
helpful, I run it with strace
. The output of strace and the program are
combined, and I can then see what it did that caused the error just prior to it
printing the message that concerns me. If the program doesn't terminate after
the first error occurs I can also pass the output to sed '/message/q'
or the
like to have it kill the program when the message is printed.
If I'm debugging in a gui, the error is probably going to come in some popup
window, and the message will not have been passed through some system call. I can print everything the program
did with strace, but finding the error in the never-stopping output is going to
take more searching than I'd like. Gui programs also tend to do more stuff to
get the same job done, so the culprit of the error is probably going to be
hidden amongst many lines of message passing system calls that are hardly
relevant to the task I needed done.