* Linux Basics


Table of Contents


This is a very brief introduction to working with Linux on the command line. It’s a collection of commands and tips&tricks that I have collected through out my Linux journey. Some of it spesific to Debian derivatives. Maybe you find something usefull too. I will probably update this from time to time. You can look at the history if you want to see whats changed.

Find OS information

Print information about your Linux distro.

lsb_release -a
cat /etc/os-release
uname -a

See how long your machine has been running since last boot.

claw0ry@lnx:~$ uptime
 11:36:40 up  4:02,  1 user,  load average: 0.00, 0.00, 0.00

Built-in documentation with manpages

In Linux we can use the man command to read built-in documentation.

man COMMAND

To list all available manpages.

man -k .

You can combine it with grep to filter the result if you are not quite sure what the manpage entry is called.

claw0ry@lnx:~$ man -k . | grep ssh
ssh (1)              - OpenSSH remote login client
ssh-add (1)          - adds private key identities to the OpenSSH authentication agent
ssh-agent (1)        - OpenSSH authentication agent
ssh-argv0 (1)        - replaces the old ssh command-name as hostname handling
ssh-copy-id (1)      - use locally available keys to authorise logins on a remote machine
ssh-keygen (1)       - OpenSSH authentication key utility
ssh-keyscan (1)      - gather SSH public keys from servers
ssh-keysign (8)      - OpenSSH helper for host-based authentication
ssh-pkcs11-helper (8) - OpenSSH helper for PKCS#11 support
ssh-sk-helper (8)    - OpenSSH helper for FIDO authenticator support
ssh_config (5)       - OpenSSH client configuration file
sshd (8)             - OpenSSH daemon
sshd_config (5)      - OpenSSH daemon configuration file
~:$ man sshd

Manage files and directories

List files and directories

# list name of files and directories under /var
ls /var

# show permissions, owners, size, modification date etc for each file and directory in /var
ls -l /var

# same as above, but also recursivly
ls -lR /var

# '-h' lists sizes in human readble format, '-F' will append a '/' to all directories
ls -lhF /var

# '-a' will also list hidden files and directories (that starts with '.')
ls -la $HOME

Finding files

# list all files and directories in /var
find /var

# list all files and directories in /var in 'ls' style
find /var -ls

# find all files that ends with '.log' in /var and execute 'type' on each file
find /var -name "*.log" -exec type {} \;

Create files

touch file.txt

vim file.txt

nano file.txt

echo "Some content" > file.txt

cat file.txt > another_file.txt

ls -lR /var > dir_list.txt

Write directly from stdin to file (also work with append).

claw0ry@lnx:~$ cat > file.txt
Write some
lines
of text
<CTRL-D>
claw0ry@lnx:~$ cat file.txt
Write some
lines
of text

Search content of files

We can use grep to search for spesific phrases/words or patterns in a file or files.

grep 'Failed' /var/log/auth.log

Search logfiles

Debian derivatives now use journalctl to display logs. Here are some basic filtering techniques.

  • ‘–since’: Filter on time. Can use ‘yesterday’, ’today’ or a datetime ‘2024-07-09’, ‘2024-07-09 18:00:00’
  • ‘–grep’: Filter using grep on the MESSAGE= field
  • ‘–unit’: Filter on the service, e.g ssh, nginx, apache2 etc
journalctl --since yesterday --grep 'failed' --unit ssh

Archiving files and directories

In Linux we use the tar command to create an archive. In most cases we also want to compress it with zip.

  • ‘c’: Create an archive
  • ‘v’: Verbose
  • ‘z’: Compress the archive with zip
  • ‘f’: Specify output file
# backup my home directory to mybackup.tar.gz
tar -cvzf mybackup.tar.gz /home/claw0ry

If we omit the ‘z’ flag, tar would create an archive with the exact same size as my homefolder.

We can list the contents of a tar archive (or tarball).

tar -tvf mybackup.tar.gz

To decompress or unpack an archive we also use tar.

  • ‘x’: Extract an archive
  • ‘C’: Use another directory than current working directory
# extract to current working directory
tar -xf mybackup.tar.gz

# or to a specific directory
tar -xf mybackup.tar.gz -C /tmp/backup

Transfer files

We can transfer files to and from other computers/servers with scp or rsync.

NOTE: If we have the same username on both ends, we dont need to specify the USER.

Using scp.

scp [src] [dest]

# from local to remote
scp [local-path] [USER@]HOST:[remote-path]

# from remote to local
scp [USER@]HOST:[remote-path] [local-path]

Using rsync.

rsync -aP [src] [dest]

# from local to remote
rsync -aP [local-path] [USER@]HOST:[remote-path]

# from remote to local
rsync -aP [USER@]HOST:[remote-path] [local-path]

# optionally we can specify -n to do a dry-run to see what would happen
rsync -naP [local-path] [USER@]HOST:[remote-path]

Real world examples.

# copy my local '.bashrc' to a lab server
scp /home/claw0ry/.bashrc lab_user@lab1.example.com:/home/lab_user/.bashrc

# sync my blog folder to webserver
rsync -aP /home/claw0ry/code/blog web.claw0ry.net:/var/www

Change permissions, owners and groups

Which files and directories can be accessed, modified etc by whom is determined by permissions and owners.

We can see the permissions and owners of a file/directory with ls.

claw0ry@lnx:~$ ls -la /home/cloud_user
total 20
drwxr-xr-x 3 cloud_user cloud_user 4096 Jul  9 08:25 .
drwxr-xr-x 4 root       root       4096 Aug 24  2023 ..
-rw-r--r-- 1 cloud_user cloud_user    1 Feb 29 19:38 .bash_history
-rw-r--r-- 1 cloud_user cloud_user    0 Feb 29 19:16 .cloud-locale-test.skip
-rw------- 1 cloud_user cloud_user   57 Jul  9 08:17 .lesshst
drwx------ 2 cloud_user cloud_user 4096 Aug 24  2023 .ssh
-rw-r--r-- 1 cloud_user cloud_user    0 Aug 28  2023 .sudo_as_admin_successful

The first character idicates what kind of item it is:

  • ‘-’: file
  • ’d’: directory
  • ’l’: symbolic link

Next we have the permissions divided into three groups. The first three are the owners permissions, then we have the groups permissions and lastly others permissions.

  • ‘-’: none
  • ‘r’: read
  • ‘w’: write
  • ‘x’: execute

The owner of the file is specified in the first column that you see cloud_user, and the group is specified in the column next to it. In this example we can see that all files and directories is owned by the cloud_user user and cloud_user group execpt for the parent directory which is owned by root user and root group.

Change owners and groups

We can change the owner and group with the chown command.

chown [-R] [OWNER][:GROUP] FILE

# only change owner
chown OWNER FILE

# only change group
chown :GROUP FILE

# change both, but not the same
chown OWNER:GROUP FILE

# change both to the same
chown OWNER: FILE
  • ‘R’: Recursive (will also change owner for all subfiles and directories)
claw0ry@lnx:~$ cd /home/cloud_user
claw0ry@lnx:~$ touch file.txt
claw0ry@lnx:~$ ls -l file.txt
-rw-r--r-- 1 cloud_user cloud_user 0 Jul  9 08:37 file.txt
claw0ry@lnx:~$ chown another_user:another_user file.txt
claw0ry@lnx:~$ ls -l file.txt
-rw-r--r-- 1 another_user another_user 0 Jul  9 08:37 file.txt
claw0ry@lnx:~$ chown cloud_user file.txt
-rw-r--r-- 1 cloud_user another_user 0 Jul  9 08:37 file.txt
claw0ry@lnx:~$ chown :cloud_user file.txt
-rw-r--r-- 1 cloud_user cloud_user 0 Jul  9 08:37 file.txt

Change permissions

To set permissions we use the chmod command.

There are two modes to set permissions with; symbolic and octal.

Octal mode
chmod OCTAL FILE
  • read(r): 4
  • write(w): 2
  • execute(x): 1

To calculate the permissions bits we just need to add the permissions together. So for read and write access it will be 4+2=6. For all permissions it will be 4+2+1=7.

Let’s say we have file.txt and we want the owner to have full permissions, the group to have read and write and others to have none. This would calculate to 760. We can set these permissions with the following command.

claw0ry@lnx:~$ chmod 760 file.txt
claw0ry@lnx:~$ ls -l file.txt
-rwxrw---- 1 cloud_user cloud_user 0 Jul  9 08:37 file.txt

These are the most common permissions used:

  • 777 (everyone has full permissions)
  • 644 (owner has read+write, and everyone else has read)
  • 750 (owner has full permissions, groups has read+execute, and everyone else has none)
  • 600 (owner is the only user that has access)
symbolic mode
chmod MODE FILE
  • ‘+’: add permission
  • ‘-’: remove permission
  • ‘=’: set permisions
  • ‘u’: owner (user)
  • ‘g’: group
  • ‘o’: others
# add read permissions for the owner
chmod u+r file.txt

# remove execute for owner
chmod u-x file.txt

# set owners permissions to read, write, execute
chmod u=rwx file.txt

We can combine permissions with ,.

claw0ry@lnx:~$ ls -l file.txt
-rwxrw---- 1 cloud_user cloud_user 0 Jul  9 08:37 file.txt
claw0ry@lnx:~$ chmod u=rwx,g=rw,o=r file.txt
claw0ry@lnx:~$ ls -l file.txt
-rwxrw-r-- 1 cloud_user cloud_user 0 Jul  9 08:37 file.txt

Input/output redirection

In Linux shells there is a concept of three streams.

  • The standard input (stdin), which takes the users input.
  • The standard out (stdout), which is the output of a command. It is usually displayed in your terminal.
  • The standard error (stderr), which is the error messages from a command. This is also usually displayed in your terminal alongside stdout.

Write errors to file instead of console.

# no redirection
claw0ry@lnx:~$ ls -l nonexisting
ls: nonexisting: No such file or directory

# with redirection of stderr
claw0ry@lnx:~$ ls -l nonexisting 2> ls_error.txt
claw0ry@lnx:~$ cat ls_error.txt
ls: nonexisting: No such file or directory

Redirect stdout to a file and only show errors in the console.

# these two are equivalent
find /root 1> dirs_i_can_read.txt
find /root > dirs_i_can_read.txt

Redirect both stdout and stderr to the same destination.

find /root 2>&1 root_dirs.txt

This tells Linux to redirect stderr to stdout and then stdout to a file.

Reboot and PowerOff

shutdown [OPTIONS] [TIME] [WALL...]
# poweroff
poweroff
shutdown -P
shutdown -P 20:00
shutdown -P +5
shutdown -P +5

# reboot
reboot
shutdown -r [TIME]
shutdown -r 20:00
shutdown -r +5 'Server will be rebooted for maintenance!'

Manage users and groups

# Add a new user
adduser LOGIN

# add user to group
gpasswd -a USER GROUP

# give sudo access
cat /etc/sudoers
gpasswd -a USER sudo

Disk space

List filesystem space usage.

claw0ry@lnx:~$ df -h
Filesystem       Size  Used Avail Use% Mounted on
udev             467M     0  467M   0% /dev
tmpfs             96M  484K   95M   1% /run
/dev/nvme0n1p1    20G  2.1G   17G  11% /
tmpfs            477M     0  477M   0% /dev/shm
tmpfs            5.0M     0  5.0M   0% /run/lock
/dev/nvme0n1p15  124M   12M  113M  10% /boot/efi
tmpfs             96M     0   96M   0% /run/user/1001
tmpfs             96M     0   96M   0% /run/user/1002

List directory space usage.

claw0ry@lnx:~$ du -hs /home/cloud_user 
36K     /home/cloud_user
claw0ry@lnx:~$ sudo du -hs /var/log
55M     /var/log

If we omit the -s we will also see subdirectories.

claw0ry@lnx:~$ sudo du -h /var/log
4.0K    /var/log/runit/ssh
8.0K    /var/log/runit
52K     /var/log/apt
4.0K    /var/log/private
53M     /var/log/journal/ec228e8f22cbefcdced18ace3b891949
53M     /var/log/journal
16K     /var/log/unattended-upgrades
32K     /var/log/amazon/ssm/audits
852K    /var/log/amazon/ssm
856K    /var/log/amazon
55M     /var/log

You can also sort the result to find what takes the most space. Since we are using the -h flag on du to get human readable sizes, we also provide the same flag to sort so that I will sort correctly.

claw0ry@lnx:~$ sudo du -h /var/log | sort -h
4.0K    /var/log/chrony
4.0K    /var/log/private
4.0K    /var/log/runit/ssh
8.0K    /var/log/runit
36K     /var/log/apt
136K    /var/log/nginx
440K    /var/log/sysstat
25M     /var/log
25M     /var/log/journal
25M     /var/log/journal/b8d53a40a48e4a9baaf67b1d19735980

To get the size of a file(s), you can use the ls command with -lh to get the size in human readable format.

Another alternative is ncdu which is an interactive version of du built with ncurses. It does not come pre-installed.

sudo apt install ncdu

# replace /home with whatevery starting path you want
ncdu /home

Now you can navigate and see the size of files and directories interactivly.

Processes

Dashboard overview of your processes, CPU and memory usage.

htop

Snapshot of the current process state.

ps aux

Kill a process.

pkill -9 PID

Schedule tasks

In Linux we use cron with a crontab file to scedule runs of commands or scripts.

The crontab template looks like this.

# +----------- minute (0 - 59)
# | +--------- hour (0 - 23)
# | | +------- day of month (1 - 31)
# | | | +----- month (1 - 12)
# | | | | +--- day of week (0 - 6) (starts at sunday)
# | | | | |
# * * * * * COMMAND
#
# NOTES
# The 'month' and 'day of week' can be represented by either a number, name or shortname.
# e.g 1, January, Jan
# e.g 1, Monday, Mon
#
# Command can be either a script or a command. You can seperate them with ';' to run
# multiple commands.
#
# Visit https://crontab.guru for a visual representation of cron schedule

To edit your crontab you use the crontab command.

crontab -e

You can also specify the user to edit crontab for if you want it to run as another user.

crontab -u USER -e

NOTE: When adding commands to your crontab, make sure you use full paths for both commands and scripts.

You can check the cron logs using journalctl.

journalctl --unit cron

Manage and update packages

dpkg

# install .deb package from file
dpkg -i FILE.deb

# list installed packages
dpkg -l

# remove package
dpkg -r NAME

# search installed packages
dpkg -S PATTERN

NOTE: When intalling packages with dpkg -i it does not perform any dependency checks. If a dependency is missing it will fail.

apt

# update package list
apt update

# upgrade installed packages
apt upgrade

# install package(s)
apt install NAME

# remove package
apt remove NAME

# remove package and config
apt purge NAME

# remove unwanted packages
apt autoremove

# search packages
apt search PATTERN

# show package details
apt show NAME

# list installed packages
apt list --installed

# list packages that can be upgraded
apt list --upgradeable