Everyday Bash and Linux commands for admins and learners, with working examples you can type as written.
Getting around
| Task |
Command |
| Where am I? |
pwd |
| Change folder, go home, go back |
cd /var/log, cd or cd ~, cd - |
| Up one level |
cd .. |
| List, long format, hidden files, human sizes |
ls -lah |
| Newest files first |
ls -lt |
| Find files by name |
find /etc -name '*.conf' |
| Files changed in the last 7 days |
find /var/log -type f -mtime -7 |
| Files over 100 MB |
find / -type f -size +100M 2>/dev/null |
| Where is a command? |
which nginx or type ls |
| Help for a command |
man ls or ls --help |
| Who am I, and what groups? |
whoami, id |
| Command history |
history, then !42 to rerun line 42 |
Files and folders
| Task |
Command |
| Make a folder (and parents) |
mkdir -p projects/site/logs |
| Create an empty file, or update its time |
touch notes.txt |
| Copy a file, copy a folder |
cp a.txt b.txt, cp -r site/ backup/ |
| Move or rename |
mv old.txt new.txt |
| Delete a file |
rm file.txt |
| Delete a folder and its contents |
rm -r oldfolder (no undo, check first) |
| Symbolic link |
ln -s /opt/app/current app |
| Show a file, page through a file |
cat file.txt, less file.txt (q quits) |
| File type and details |
file mystery.bin, stat file.txt |
Permissions and ownership
In ls -l output such as -rwxr-xr-x, the three groups of letters are owner, group, others. Numbers add up per group: read 4, write 2, execute 1.
| Numeric |
Letters |
Typical use |
chmod 755 script.sh |
rwxr-xr-x |
Scripts and folders everyone may enter |
chmod 644 page.html |
rw-r--r-- |
Normal files: owner edits, others read |
chmod 640 app.conf |
rw-r----- |
Config the group may read, others may not |
chmod 600 ~/.ssh/id_ed25519 |
rw------- |
Private keys and secrets |
chmod 700 ~/private |
rwx------ |
Folder only you can use |
| Task |
Command |
| Add or remove one permission |
chmod u+x deploy.sh, chmod g-w file, chmod o-rwx file |
| Apply to a whole tree |
chmod -R 750 /srv/app |
| Change owner and group |
sudo chown alice:developers report.txt |
| Change owner for a whole tree |
sudo chown -R www-data:www-data /var/www/site |
| Change group only |
chgrp developers report.txt |
| Default permissions for new files |
umask (022 gives files 644 and folders 755) |
| Run one command as root |
sudo systemctl restart nginx |
Working with text
| Task |
Command |
| Lines containing a word (case-insensitive) |
grep -i error app.log |
| Search a folder, show line numbers |
grep -rn 'listen' /etc/nginx/ |
| Lines that do not match |
grep -v '^#' app.conf |
| Count matching lines |
grep -c 'Failed password' /var/log/auth.log |
| Match either of two patterns |
grep -E '404|500' access.log |
| First or last N lines |
head -n 20 file, tail -n 50 file |
| Follow a log live (Ctrl+C stops) |
tail -f /var/log/syslog |
| Pick a column from delimited text |
cut -d: -f1 /etc/passwd |
| Sort, numerically, in reverse |
sort names.txt, sort -n, sort -r |
| Sort by the 3rd field of : separated text |
sort -t: -k3 -n /etc/passwd |
| Remove repeats (sort first) |
sort list.txt | uniq |
| Tally values, most common first |
sort list.txt | uniq -c | sort -rn |
| Count lines, words, bytes |
wc -l file, wc -w file, wc -c file |
sed and awk one-liners
| Task |
Command |
| Replace text in the output |
sed 's/old/new/g' file.txt |
| Replace text in the file itself (GNU sed) |
sed -i 's/old/new/g' file.txt |
| Print lines 10 to 20 |
sed -n '10,20p' file.txt |
| Delete comment lines |
sed '/^#/d' app.conf |
| Print the first column |
awk '{print $1}' access.log |
| Use : as the separator |
awk -F: '{print $1, $7}' /etc/passwd |
| Rows where column 9 is 404 |
awk '$9 == 404' access.log |
| Sum a column |
awk '{sum += $10} END {print sum}' access.log |
| Top 10 client IPs in a web log |
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head |
On macOS and BSD, sed -i needs an empty backup suffix: sed -i '' 's/old/new/g' file.
Processes and services
| Task |
Command |
| All processes |
ps aux |
| Top memory users |
ps aux --sort=-%mem | head |
| Find a process by name |
pgrep -a nginx |
| Live view (q quits) |
top (or htop if installed) |
| Ask a process to stop |
kill 1234, pkill nginx |
| Force stop (last resort) |
kill -9 1234 |
| Run in the background, list jobs |
long_task &, jobs, fg %1 |
| Service status, start, stop, restart |
systemctl status nginx, sudo systemctl restart nginx |
| Start now and at every boot |
sudo systemctl enable --now nginx |
| Failed services |
systemctl list-units --failed |
Disk and memory
| Task |
Command |
| Free space per filesystem |
df -h |
| Size of a folder |
du -sh /var/log |
| Biggest items one level down |
du -h --max-depth=1 /var | sort -h |
| Memory in use (human, or MB) |
free -h, free -m |
| Disks and partitions |
lsblk |
| What is mounted where |
findmnt or mount |
| Uptime and load average |
uptime |
System logs with journalctl
| Task |
Command |
| Errors and worse |
journalctl -p err |
| Errors since this boot |
journalctl -p err -b |
| One service |
journalctl -u nginx |
| Follow new entries live |
journalctl -f or journalctl -u nginx -f |
| Last 50 entries |
journalctl -n 50 |
| Recent time window |
journalctl --since '1 hour ago', --since today |
| Previous boot |
journalctl -b -1 |
| Kernel messages |
journalctl -k or dmesg |
| How much space logs use |
journalctl --disk-usage |
You may need sudo or membership of the adm or systemd-journal group to see all entries.
Redirection and pipes
| Symbol |
Meaning |
Example |
> |
Send output to a file (overwrite) |
ls > files.txt |
>> |
Append to a file |
date >> run.log |
2> |
Send errors to a file |
find / -name x 2> errors.txt |
2>&1 |
Send errors where output goes |
./backup.sh > backup.log 2>&1 |
&> |
Output and errors to a file (Bash) |
./backup.sh &> backup.log |
< |
Read input from a file |
wc -l < access.log |
| |
Pipe output into the next command |
ps aux | grep nginx |
tee |
Show output and save it |
make 2>&1 | tee build.log |
/dev/null |
Throw output away |
cmd > /dev/null 2>&1 |
$( ) |
Use a command’s output |
echo "Today is $(date +%F)" |
&& || |
Run next only on success, or only on failure |
mkdir out && cd out or ping -c1 host || echo down |
$? |
Exit code of the last command (0 is success) |
echo $? |
A tiny script skeleton
#!/usr/bin/env bash
# Stop on errors, unset variables and failed pipes
set -euo pipefail
logdir="${1:-/var/log}" # first argument, or a default
if [[ ! -d "$logdir" ]]; then
echo "No such folder: $logdir" >&2
exit 1
fi
for f in "$logdir"/*.log; do
[[ -e "$f" ]] || continue
echo "$f: $(wc -l < "$f") lines"
done
Save as count-logs.sh, then chmod +x count-logs.sh and run ./count-logs.sh /var/log. Always quote variables: "$f".