Bash tips for Linux server admin

Before you begin

In this tutorial we’ll learn some bash commands that can be useful for Linux server administration. A Linux machine is required to follow this tutorial.

1. Check what ports are listening using lsof

All ports listening:

$ sudo lsof -i -P -n | grep LISTEN

Checking a specific port like port 8000:

# Starting a server on port 8000
$ python -m SimpleHTTPServer

# Checking port 8000
$ sudo lsof -i :8000 -P
python  ...  TCP *:8000 (LISTEN)

2. Find patterns and instance search in less

Find patterns in less in 3 steps:

Provide a file to less command:

$ less file.txt

Press & keyboard and write a string to search, in this example the string error:


Finally, press enter and all matches will be printed.

Instance search in less

Searches for a pattern inside of the file, in this example error as well:

$ less -perror file.txt
# press n to find the next one.

3. Comments in iptables rules

Always come in handy to have a comment near an iptable rule explaining what it does. Example:

$ iptables -A INPUT -s [EXTERNAL_SERVER] \
  -m comment --comment "Allows external server to reach port 80" \
  -p tcp --dport 80 -j ACCEPT
ACCEPT tcp -- [EXTERNAL_SERVER] anywhere /* Allows external server to reach port 80 */ tcp dpt:http

After that we cannot forget to save the iptables to make them available after the next reboot:

$ sudo cp /etc/iptables/rules.v4 /etc/iptables/rules.v4.bkp
$ sudo iptables-save > /etc/iptables/rules.v4

Previous commands can vary depending on the Linux distribution and version.

4. List files by size using du and sort

Displays the size of files and directories of the current folder:

/var/log/nginx$ du -sh * | sort -h
4.0K	error.log.1
4.0K	error.log.2.gz
4.0K	error.log.3.gz
8.0K	error.log
60K	access.log.3.gz
76K	access.log.2.gz
1.1M	access.log
1.2M	access.log.1

5. Using verbose to copy, move or remove files

Verbose mode including -v parameter:

# copy
$ cp -v 0 1
'0' -> '1'

# copy -R/--recursive
$ mkdir -p 1/2/3
$ cp -Rv  1 foo
'1' -> 'foo'
'1/2' -> 'foo/2'
'1/2/3' -> 'foo/2/3'

# rename
$ mv -v 1 2
renamed '1' -> '2'

# remove
$ rm -v 2
rm: remove regular empty file '2'? y
removed '2'

Write all last history commands to .bash_history, useful when we are using one single terminal:

$ history -w

Write all last history commands to .bash_history automatically from multiple terminals and also making available to them:

export HISTCONTROL=ignoreboth:erasedups
export HISTSIZE=100000
export HISTFILESIZE=100000
export PROMPT_COMMAND="history -a; history -c; \
       history -r; $PROMPT_COMMAND"
shopt -s histappend

Repeat last command executed using !! :

$ echo "bar"
$ !!
echo "bar"

# Useful when you forget to type sudo for example:
$ mkdir /opt/foo
mkdir: cannot create directory ‘/opt/foo’: Permission denied
$ sudo !!
sudo mkdir /opt/foo

7. Set avoiding commands to go to history

To prevent a command to go to history we should follow two rules:

1) Set HISTCONTROL to ignorespace (or ignoreboth if we also want to prevent duplicates to going to history as well).
2) Start the command with an empty single space.


$ export HISTCONTROL=ignoreboth # ignoredups and ignorespace
$ echo "this totally exists"
$  echo "this never exists" # because contains a space

Note: HISTCONTROL can be overridden automatically in the .bashrc file.

8. Display kernel version and OS release

uname and etc/os-release are common in the vast majority of Linux versions:

$ cat /etc/os-release
NAME="Alpine Linux"
PRETTY_NAME="Alpine Linux v3.12"

$ uname -a
Linux 104dda9b403d 5.2.11-100.fc29.x86_64
#1 SMP Thu Aug 29 12:52:22 UTC 2019 x86_64 Linux

9. Curly brace expansion in bash examples

Printing the following five strings:

$ echo test{1,2,,foo,bar}
> test1 test2 test testfoo testbar

Creating five files:

$ touch test_{1..5}
$ ls
> test_1  test_2  test_3  test_4  test_5

10. List all files by last modified date

Using ls:

$ ls -latr

# human readable size of the files/folder
$ ls -latrh

11. Going to previous git branch using git checkout -

From develop branch to creating a new foo branch and returning back to develop:

/my_workspace/my_repo(develop)$ git checkout -b foo
Switched to a new branch 'foo'
/my_workspace/my_repo(foo)$ git checkout -
Switched to branch 'develop'
Your branch is up to date with 'origin/develop'.

12. Installing telnet on Alpine Linux

telnet comes as part of the busybox-extras tools and can be called like busybox-extras telnet. Example:

$ apk add -u busybox-extras
$ busybox-extras --list
$ busybox-extras telnet 80

13. Checking last reboot time

The quick way is to use uptime:

$ uptime
 07:18:40 up 11 days,  ...

Last reboot was 11 days ago. But if we need to know the exact date and time it is better last reboot:

$ last reboot
reboot   system boot  ... Sun Jun 21 23:19 - 07:16  (16:53)

# or even better with -F parameter
$ last reboot -F
reboot   system boot  ... Sun Jun 21 23:19:01 2020   still running

We can see that last reboot was on Sun Jun 21 23:19:01 2020.

Finally, you should definitely take a look at these books to fuel your Linux knowledge: