Bash Tips - Tip 1
Recently, I was pairing with a developer on a client’s team. He was stuck and couldn’t figure out how to fix the problem. I had a look and guided him through a series of bash and other shell commands until we found the solution. After thanking me – he had been at it for hours – he asked me “How do you know all of this?” I could tell from his tone that what he was really asking was “From what book did you learn all of this?” Thing is, I didn’t learn “all of this” from a book. Having been at it since 1997, I learned it through good old fashioned trial and error. That and being exposed to new tools.
That conversation sparked the idea that I should share this knowledge through a series of posts. My goal is to make it easily accessible for all who could use this information. If you have pressing needs, let me know, and I might cover that tip next.
For now, here’s tip number one:
alias is similar in the real world as it is in a shell. So if we look at the
ls command, which lists all of the files in the current directory, we’ll see something like this.
$ ls -a . .. .bash_profile .git .tmux.conf .vimrc README.md alacritty.yml
What if we want this list to be vertical and show file sizes in human-readable format? The command would be:
$ ls -alh total 48 drwxr-xr-x 8 david staff 272B Jan 11 09:41 . drwxr-xr-x+ 117 david staff 3.9K Feb 22 11:27 .. -rw-r--r-- 1 david staff 2.2K Nov 30 17:00 .bash_profile drwxr-xr-x 14 david staff 476B Sep 23 13:09 .git -rw-r--r-- 1 david staff 1.2K Jun 28 2016 .tmux.conf -rw-r--r-- 1 david staff 2.6K Jan 26 01:04 .vimrc -rw-r--r-- 1 david staff 79B Oct 12 2014 README.md -rw-r--r-- 1 david staff 7.3K Jan 11 09:49 alacritty.yml
And if we want to be able to access this quickly, we can set it up as an alias.
$ alias lh='ls -alh'
Now, anytime we type
lh into our shell, it will give us the same output.
$ lh total 48 drwxr-xr-x 8 david staff 272B Jan 11 09:41 . drwxr-xr-x+ 117 david staff 3.9K Feb 22 11:27 .. -rw-r--r-- 1 david staff 2.2K Nov 30 17:00 .bash_profile drwxr-xr-x 14 david staff 476B Sep 23 13:09 .git -rw-r--r-- 1 david staff 1.2K Jun 28 2016 .tmux.conf -rw-r--r-- 1 david staff 2.6K Jan 26 01:04 .vimrc -rw-r--r-- 1 david staff 79B Oct 12 2014 README.md -rw-r--r-- 1 david staff 7.3K Jan 11 09:49 alacritty.yml
However, if we want this
alias to persist, we need to store it somewhere. When using
bash, there’s a config file we can reference. For nix systems, it should be
~/.bashrc, and for Mac OS X,
~/.bash_profile. This file is used when the shell starts to set up its environment. This file will most likely already exist, so let’s add our new alias.
# Setup Alias for lh alias lh='ls -alh'
This is in the config for
bash, but our current shell has the old configuration loaded. To load the new config changes, we need to
source this file.
$ source ~/.bash_profile
Now, our current shell and any future ones will have our new
SSHing into Different Machines
If you’ve ever used an Amazon EC2 instance, set up a local Virtual Machine (VM), or accessed another machine across the internet, you might have used
ssh, which stands for Secure SHell. A typical connection might look like this:
ssh ssh.someserver.com -l myusername -p 9000 -i "~/.ssh/my_keyfile.pem"
Since I don’t want to have to remember this all the time, what are my options?
I could create an alias for this connection:
# include in ~/.bash_profile or ~/.bashrc alias ssh-someserver='ssh ssh.someserver.com -l myusername -p 9000 -i "~/.ssh/my_keyfile.pem"'
This works, but the list could grow quite large if we have numerous servers we need to connect to.
And… there is a built-in solution to handle this with
ssh uses the path
~/.ssh/config as a place to look up information if it is available. This means we can add the connection information to this server and access it with
# include in ~/.ssh/config Host someserver Hostname ssh.someserver.com Port 9000 User myusername IdentityFile "~/.ssh/my_keyfile.pem"
Now, all we have to do is use the
Host name to
ssh into this machine.
And all we have to remember now is which server we want to connect to and type its name after
ssh. The added benefit is this config file works with other
ssh tools like
Securely Copy Files
scp command works similarly to the
cp command, but can access other machines via
scp someserver:~/project/README.md ~/Downloads/project-README.md
Here, we’re going to copy the
README.md file from the
project folder on the
someserver box and put it into our local
Downloads folder, but rename it to
project-README.md since we want to know which readme this is for.
Stopping a Local Process
There are times when we might leave our
ssh session open and, after a period of time or if the internet connection is lost, the
ssh session will become unresponsive. If we weren’t running an active task remotely, the
ssh session isn’t really “hung,” but rather, it’s trying to re-establish a connection. This can be frustrating if we know the connection won’t go through as that
bash session will not be usable.
The quickest way, that I have found, to get control of that window back is the following:
- Start a new Terminal/bash window.
ps aux | grep ssh.
- Find the
pidof the “hung”
The goal here is to find the
ssh session that most likely will fail anyway and tell it to exit. This is what it would look like:
$ ps xao user,pid,comm | grep ssh david 16510 vim .ssh/config david 21462 /usr/bin/ssh-agent -l david 16738 grep --color -E ssh david 16733 ssh my_remote_server $ kill 16733
Typically, I use
ps aux, but for formatting reasons on this post, I thought it would be helpful to only show the username (user) of the active process, the process id (pid) – to determine what to pass to the
kill command – and the command (comm) itself.
kill command most likely won’t show anything in the second shell we are using, but in the first shell, that
ssh connection will end up looking something like this:
myusername@someserver:~$ Killed by signal 15. $
A lot of developers just use the
kill -9 command. This specifies the signal to send to the program. The list of kill signals can be found on the
kill man page.
Some of the more commonly used signals: 1 HUP (hang up) 2 INT (interrupt) 3 QUIT (quit) 6 ABRT (abort) 9 KILL (non-catchable, non-ignorable kill) 14 ALRM (alarm clock) 15 TERM (software termination signal)
So if we had used that instead, we would have seen this in the first shell.
myusername@someserver:~$ Killed: 9 $
If you need clarification on this tip, just ask in the comments below. I’d love to help! And remember, if you have questions about bash and other shell commands, let me know, and I might cover that topic next.