This cheat sheet provides a quick reference guide for common Linux and shell commands. Whether you’re a beginner or an experienced user, these commands will help you navigate the Linux environment more efficiently.
Services
# list systemd units
systemctl list-units --no-pager --type=service
# service status
systemctl status ufw.service
systemctl stop sshd
systemctl start sshd
systemctl status sshd
systemctl is-active sshd
systemctl is-failed sshd
systemctl restart sshd
systemctl reload sshd # re-reads the configuration of the service configs
systemctl daemon-reload sshd # re-reads the configuration of the systemd configs of this service
systemctl enable sshd
systemctl disable sshd
systemctl is-system-running # running, degraded, maintenance, initializing, starting, stopping
systemctl --failed
journalctl # show all journal
journalctl --no-pager # do not use less
journalctl -n 10 # only 10 lines
journalctl -S -1d # last 1 day
journalctl -xe # last few logs
journalctl -u ntp # only ntp unit
journalctl _PID=1234
Text filtering
# sort by filesize
ls -lS /path/to/folder/
# cat -n gives line numbers
ls | cat -n
# line numbering
nl test.txt
# split file in 10 lines
split -l 10 test.txt prefix_
# get back original file
cat filename* > originalfile
# tail logs
tail -f logs.txt
# split text into 1-2,4 parts with delimiter ' '
cut -d ' ' -f 1-2,4 test.txt
# shuffle lines
shuf test.txt > shuffled.txt
# sort
sort test.txt
# unique line filtering and count
sort test.txt | uniq -c
# replace chars
cat test.txt | tr 'o' 'O'
# count lines
wc -l test.txt
# count words in file
cat file.txt | grep -o -i example | wc -l
# sed regex
sed -r "s/(Z|R|J)/starts with ZRJ/" friends.txt
# substitute (find and replace) "foo" with "bar" on each line
sed 's/foo/bar/' # replaces only 1st instance in a line
sed 's/foo/bar/4' # replaces only 4th instance in a line
sed 's/foo/bar/g' # replaces ALL instances in a line
sed 's/\(.*\)foo\(.*foo\)/\1bar\2/' # replace the next-to-last case
sed 's/\(.*\)foo/\1bar/' # replace only the last case
# substitute "foo" with "bar" ONLY for lines which contain "baz"
sed '/baz/s/foo/bar/g'
grep
# extended regex grep
grep -E "a|b" words
Disk Layout & Filesystem Hierarchy Standard (FHS)
fdisk /dev/sda
mount
Debugging boot loader (grub2)
cat /boot/efi/EFI/ubuntu/grub.cfg
Debian package management
# pkg sources
cat /etc/apt/sources.list
# check the files and directories a package installed
dpkg -L bzr
# fix broken pkgs
apt install -f
# show pkg info
apt info pkg
# search pkg
apt search pkg
# rm unneeded pkg deps
apt autoremove
Basic Shell Stuff
# what shell is used
readlink /bin/sh # or echo $SHELL
# find out stuff about bins
which ls
whatis ls
whereis ls
# current location
pwd
# info on system
uname -a
# add stuff to PATH
PATH=$PATH:~/opt/bin # persist in .profile
# run last cmd
!!
Basic Hashing
md5sum test.txt
sha256sum test.txt
sha512sum test.txt
File Management
# copy 3 letter files
cp ???.* /tmp
# move files containing _.
mv *[_.]* /tmp
# create nested dirs
mkdir -p test/test1/test2
# check file type
file test.txt
# list only files
ls -p | grep -v /
# find case insensitive files starting with a-c
find . f -iname "[a-c]*"
# find & exec on all files altered in the last hour
find . -mmin -60 -exec echo {} \;
# find & rename
find . -name "*.htm" -exec mv '{}' '{}l' \;
Compression
# zip
gzip test.txt
# unzip
gunzip test.txt
# tar & compress
tar cvzf file.tar.gz *.txt
# tar extract
tar xvzf file.tar.gz
Streams, Redirects, Pipes
Streams: 0 stdin, 1 stdout, 2 stderr
Symbol | Description |
---|---|
> | STDOUT to file (overwrite) |
>> | STDOUT to file (append) |
2> | STDERR to file (overwrite) |
2>> | STDERR to file (append) |
&> | STDOUT & STDERR to file (overwrite) |
&>> | STDOUT & STDERR to file (append) |
< | STDIN from file |
<> | Redirect STDIN from the file and send the STDOUT to it |
# example
$ ls
bob jack jadi linus sara who_uses_what.txt
$ ls x*
ls: x*: No such file or directory
$ ls j*
jack jadi
$ ls j* x* > output 2> errors
$ cat output
jack
jadi
$ cat errors
ls: x*: No such file or directory
# &1 and &2 and &0 to refer to the target of STDOUT, STDERR & STDIN
# example: redirect output to file1 and output stderr to same place as stdout (file1)
ls > file1 2>&1
# send errs into abyss
ls j* x* > file1 2>/dev/null
# pipes
cut -f2 -d, who_uses_what.txt | sed -e 's/ //g' | sort | uniq -c | sort -nr
xargs & tee
# execute sth on lines
ls -1 | xargs -I HERE echo these HERE are files
# tee (2x stdout)
ls | tee file.txt
Managing Processes
# show processes
ps -aux | less
ps -A
ps -e | grep -E 'firefox|chrome'
pstree # tree like process view
# info on threads
ps -eLf
# lookup process by name
pgrep docker
# run binary in background
somebin &
# check jobs with process id
jobs -l
# bring job back to foreground
fg %1
# run independent of shell
nohup script.sh > mynohup.out 2>&1 &
# kill process
kill 8733
kill -15 8733 # default (TERM)
kill -9 8733 # force kill (KILL)
# kill by name
pkill docker
# kill all ps with given name
killall sleep
uptime
# 13:51:49 up 161 days, 4:56, 1 user, load average: 0.00, 0.05, 0.02
top
key during top | functionality |
---|---|
h | help |
q | quit |
M | sort based on memory usage |
c | show full commands |
k | kill after asking pid and signal |
P | sort based on CPU usage |
tmux
The default command prefix is Ctrl+B
and after running the tmux new
you can issue these:
Key | Usage |
---|---|
% | Split current window vertically |
” | Split current window horizontally |
D | Detach from the current window |
& | Kill current window |
c | new window |
You can list the tmux sessions using tmux ls
and re-attach to one using tmux att
to connect to the last one or tmux att -t session_name
to attach to a specific one.
Filesystem Checking
# free & used space on file systems
df -h
# check used space on specific dirs
du -h .
du -h --max-dept 1 /home/
# show block devices
lsblk
# check filesystem
fsck /dev/sdb
# show auto mounts
cat /etc/fstab
# list mounted fs
mount
# mount & unmount
sudo mount -t ext4 /dev/sda3 /media/mydisk
sudo umount /dev/sda3
sudo umount /media/mydisk
File Permissions & Ownership
Symbolic | Octal |
---|---|
rwx | 7 |
rw- | 6 |
r-x | 5 |
r— | 4 |
-wx | 3 |
-w- | 2 |
—x | 1 |
--- | 0 |
Generally: 755 for general executable files or 600 for personal files |
# user
whoami
# groups membership
groups
# show user id, group id & groups
id
# change file ownership & permissions
chmod u=rxw,g=rw,o= test.txt
chown user:group test.txt
User & Group Management
# change password
passwd
passwd newuser
# add user
adduser newuser
# delete user
userdel newuser
# change groups
chgrp group test.txt
# add group
groupadd -g 1200 newgroup
groupdel newgroup
newgrp lxd
# add user to sudo group (addGroup)
usermod -aG sudo user
# check persisted users & groups
cat /etc/passwd
# hashed passwords
cat /etc/shadow
# change password
chage -l user
chage user
Hard und Symbolic Links
# symlink (soft)
ln -s file_a file_b
# hard link
ln new_file hard_link
# find links
find . -type l
Bash Scripting
- Unofficial Bash Strict Mode:
set -euxo pipefail
# one-liner: check if file exists
[ ! -f foo.txt ] && echo "File not found!"
[ ! -f foo.txt ] && echo "File not found" || echo "file found"
# or: conditional
if [ ! -f /tmp/foo.txt ]; then
echo "File not found!"
fi
# check for parameter
if [ $# -ne 1 ]
then
echo "I need 1 parameter"
exit 1
else
echo "starting"
cd /tmp
touch $($date +'%Y%m%d-%H%m')-$1
ls -ltrh | tail -3
echo "done"
exit 0
fi
# check last return code
echo $?
Conditionals
The command to check conditions is the test
command but since it is used a lot, we have a shortcut for it. Instead of test condition
you can write [ condition ]
.
conditions | what is means |
---|---|
”a” = “b” | if two strings are equal (here it will return False) |
“a” != “b” | string a is not equal to string b |
4 -lt 40 | if 4 is lower than 40 (True) |
5 -gt 15 | if 5 is greater than 15 (False) |
5 -ge 5 | if 5 is greater or equal 5 |
5 -le 3 | if 5 is lower or equal to 3 |
9 -ne 2 | 9 is not equal with 2 (True) |
-f FILENAME | if file FILENAME exists |
-s FILENAME | if file exists and its size is more than 0 (Zero) |
-x FILENAME | if file exists and is executable |
Note that [[
is actually a command/program that returns either 0
(true) or 1
(false). Any program that obeys the same logic (like all base utils, such as grep(1)
or ping(1)
) can be used as condition, see examples.
conditions | what is means |
---|---|
[[ -z STRING ]] | Empty string |
[[ -n STRING ]] | Not empty string |
[[ STRING == STRING ]] | Equal |
[[ STRING != STRING ]] | Not Equal |
[[ NUM -eq NUM ]] | Equal |
[[ NUM -ne NUM ]] | Not equal |
[[ NUM -lt NUM ]] | Less than |
[[ NUM -le NUM ]] | Less than or equal |
[[ NUM -gt NUM ]] | Greater than |
[[ NUM -ge NUM ]] | Greater than or equal |
[[ STRING =~ STRING ]] | Regexp |
(( NUM < NUM )) | Numeric conditions |
[[ -o noclobber ]] | If OPTIONNAME is enabled |
[[ ! EXPR ]] | Not |
[[ X && Y ]] | And |
[[ X | Y ]] | Or |
File conditions:
conditions | what is means |
---|---|
[[ -e FILE ]] | Exists |
[[ -r FILE ]] | Readable |
[[ -h FILE ]] | Symlink |
[[ -d FILE ]] | Directory |
[[ -w FILE ]] | Writable |
[[ -s FILE ]] | Size is > 0 bytes |
[[ -f FILE ]] | File |
[[ -x FILE ]] | Executable |
[[ FILE1 -nt FILE2 ]] | 1 is more recent than 2 |
[[ FILE1 -ot FILE2 ]] | 2 is more recent than 1 |
[[ FILE1 -ef FILE2 ]] | Same files |
examples
# String
if [[ -z "$string" ]]; then
echo "String is empty"
elif [[ -n "$string" ]]; then
echo "String is not empty"
else
echo "This never happens"
fi
# Combinations
if [[ X && Y ]]; then
...
fi
# Equal
if [[ "$A" == "$B" ]]
# Regex
if [[ "A" =~ . ]]
# smaller than
if (( $a < $b )); then
echo "$a is smaller than $b"
fi
# if file exists
if [[ -e "file.txt" ]]; then
echo "file exists"
fi
Loops
#!/bin/bash
for NUM in {1..5};
do
echo $NUM
done
while
VAR=52
# while greater than
while [ $VAR -gt 42 ]
do
echo VAR is $VAR and it is still greater than 42
let VAR=VAR-1 # let for calc on vars
done
Arrays
# Define an array
$ Fruits=('Apple' 'Banana' 'Orange')
Fruits[0]="Apple"
Fruits[1]="Banana"
Fruits[2]="Orange"
# Working with arrays
echo "${Fruits[0]}" # Element #0
echo "${Fruits[-1]}" # Last element
echo "${Fruits[@]}" # All elements, space-separated
echo "${#Fruits[@]}" # Number of elements
echo "${#Fruits}" # String length of the 1st element
echo "${#Fruits[3]}" # String length of the Nth element
echo "${Fruits[@]:3:2}" # Range (from position 3, length 2)
echo "${!Fruits[@]}" # Keys of all elements, space-separated
# Operations
Fruits=("${Fruits[@]}" "Watermelon") # Push
Fruits+=('Watermelon') # Also Push
Fruits=( "${Fruits[@]/Ap*/}" ) # Remove by regex match
unset Fruits[2] # Remove one item
Fruits=("${Fruits[@]}") # Duplicate
Fruits=("${Fruits[@]}" "${Veggies[@]}") # Concatenate
lines=(`cat "logfile"`) # Read from file
# Iteration
for i in "${arrayName[@]}"; do
echo "$i"
done
Directories
# Declare a directory
declare -A sounds
sounds[dog]="bark"
sounds[cow]="moo"
sounds[bird]="tweet"
sounds[wolf]="howl"
# Working with dictionaries
echo "${sounds[dog]}" # Dog's sound
echo "${sounds[@]}" # All values
echo "${!sounds[@]}" # All keys
echo "${#sounds[@]}" # Number of elements
unset sounds[dog] # Delete dog
# Iteration: values
for val in "${sounds[@]}"; do
echo "$val"
done
# Iteration: keys
for key in "${!sounds[@]}"; do
echo "$key"
done
Command Substitution
TODAY=$(date +'%Y %m %d - %H:%m')
echo $TODAY
name="John"
echo "${name}"
echo "${name/J/j}" #=> "john" (substitution)
echo "${name:0:2}" #=> "Jo" (slicing)
echo "${name::2}" #=> "Jo" (slicing)
echo "${name::-1}" #=> "Joh" (slicing)
echo "${name:(-1)}" #=> "n" (slicing from right)
echo "${name:(-2):1}" #=> "h" (slicing from right)
echo "${food:-Cake}" #=> $food or "Cake"
Cron
# list cronjobs
crontab -l
# edit cronjobs
crontab -e
A B C D E command and arguments
filed | Meaning | values |
---|---|---|
A | minute | 0-59 |
B | hour | 0-23 |
C | day of month | 1-31 |
D | month | 1-12 (or names, see below) |
E | day of week | 0-7 (0 or 7 is Sunday, or use names) |
If you replace a field with *
it means “whatever” or “all” or “any”. Also if you have @reboot
or @daily
instead of time fields, the command will be run once after the reboot or daily. Lets see some examples:
5 0 * * * $HOME/bin/daily.job >> $HOME/tmp/out 2>&1
# run at 2:15pm on the first of every month -- output mailed to paul
15 14 1 * * $HOME/bin/monthly
# run at 10 pm on weekdays, annoy Joe
0 22 * * 1-5 mail -s "It's 10pm" joe%Joe,%%Where are your kids?%
23 0-23/2 * * * echo "run 23 minutes after midn, 2am, 4am ..., everyday"
5 4 * * sun echo "run at 5 after 4 every sunday"
*/5 * * * * echo "each 5 mintues"
42 8,18 * * 1-5 echo "8:42 and 18:42 and only on weekdays (monday till friday)"
@reboot echo "runs after the reboot"
System & Boot Logs
# kernel ring buffer logs
dmesg
# check log rotation
cat /etc/logrotate.conf # usually in /etc/cron.daily
# system log management
systemctl status rsyslog
cat /etc/rsyslog.conf # config
journalctl # show all journal
journalctl -xe # last few logs
journalctl --no-pager # do not use less
journalctl -n 10 # only 10 lines
journalctl -S -1d # last 1 day
journalctl -u nginx.service --since today # only nginx unit
journalctl _PID=1234 # by process id
Network Troubleshooting
# show NICs
ip link show
ip addr show
ifconfig -a # old
# hostname
hostname
hostnamectl status
cat /etc/hostname
# remote host: return DNS records (& get ip)
host google.com
host -t TXT google.com
# routing
ip route
ip route add default via 172.31.1.1 # default gateway
ip route add 4.2.2.4 via 172.31.1.1 # static route
# trace
traceroute google.com
# netstat & ss: check open ports (LISTEN)
netstat -tulpen # old
ss -tulpen
# check which user & command is using port
sudo fuser 3000/tcp -v
# set DNS server
cat /etc/resolv.conf
# netcat: listen on port
nc -l 8080
# netcat: check if remote port is open
nc -zv localhost 8080
nc -zv localhost 1-9999
# dig: check dns
dig @8.8.8.8 google.com
# tcpflow & tcpdump
tcpflow -c port 80
tcpdump -i eth0
Administration & Security
# change to root with env vars
sudo su -
# change to user
su newuser -
# check system sessions
w
who
# last logins
last
last -f /var/log/btmp # failed logins
# suid & guid
find /usr/bin/ -perm -u+s
# show open files
lsof
sudo lsof -i # show open connection files
ssh
# generate ssh key pair in ~/.ssh
ssh-keygen -t ed25519
# ssh agent
ssh-agent /bin/bash
ssh-add # add all keys to agent
# ssh tunnel: enable processes running at foo to connect
# to `localhost:8080` and actually speak to your home computer at port # 3000
ssh -R 8080:localhost:3000 foo.mycompany.com