Note
18/7/2026: "Backup a directory of files", "Mount devices" and "Set up SSH keys to access remote computer" updated, and "Define time scheduled jobs" and "Install Chrony" sections added.
15/7/2026: "Update firmware" section added.
6/7/2026: More commands added to view system information.
23/4/2026: "Switch user" section added.
3/2/2026: "Recreate deleted user with specific UID" and "Recreate mailbox-only account" sections added.
29/1/2026: "micro" added as an editor. "gksudo gedit" removed.
29/7/2022: Setting up SSH keys added.
18/4/2022: cp -Rav added.
14/4/2022: Command to delete multiple empty sub-directories added.
18/12/2021: Updated.
6/10/2018: Updated.
27/9/2018: Updated.
21/3/2018: Updated.
27/8/2017: Created.
Intro
$ = the terminal command prompt against which commands are entered.
sudo = superuser acting as the root user.
<text> = information to be entered, angle brackets themselves are not to be entered.
[abc] = options a, b and c, brackets are not necessary.
Capitals and small letters behave differently.
Switch user
(section added, 23/4/2026)
Precede a terminal command with "sudo" if acting like the root user is required.
$ sudo <command statement>- Files created to be owned by the superuser.
Switch to act as the root user:
$ sudo -iExit root:
# exitSwitch to act as another user, and exit later:
$ sudo -u <another_name> -i
$ exit- No need to precede with sudo.
- Cannot act as the root user.
- Files created to be owned by "another_name".
View system information
(more commands added, 6/7/2026)
Show who am I:
$ whoamiShow current date and time:
$ dateShow this month's calendar:
$ calList processes with details like user ids, process ids (PID), CPU/memory usages, and commands of the current user:
$ ps auxor
$ ps -ef- showing less columns
or
$ ps aux | less- giving a progressive list
or
$ ps aux | grep dovecot- filter to show lines containing "dovecot"
or
$ ps -f- showing processes in the current terminal session
Show process id of a process by name:
$ pgrep -l dovecotList commands and process ids of the current user:
$ lsof -iList commands and process ids of all users:
$ sudo lsof -iShow real-time view of running processes:
$ top- press "q" to exit
- press "Shift + P" to sort by CPU
- press "Shift + M" to sort by memory
Aternatively:
$ htop- press "F10" to exit
List active internet connections (only servers)
$ sudo netstat -lptuor
$ sudo netstat -lptunDisplay disk space:
$ dfDisplay disk space in a more readable format:
$ df -hDisplay file contents:
$ cat <directory>/<sub-directory>/<filename>Use path and file names
<directory path> = <directory>/<sub-directory> referring from the current directory, without filename stated.
<filename path> = <directory>/<sub-directory>/<filename> referring from the current directory.
Precede with "/" if referring the path from the root directory. Deleting files under a sub-directory but incorrectly referring to the root directory is dangerous. Better avoid referring from the root directory.
Use "*" as a wildcard to represent texts before or after directory or file name, e.g. "*name", "name*" or "*" for any name.
Use "." alone to represent the current directory.
Use "../" to represent the directory immediately above the current directory.
Use "/." at the end to represent all under the stated <directory path>, e.g. "<sub-directory>/."
Search things
Find files with filenames containing <filename> in <directory path>:
$ find <directory path> -name "<filename>"Use "-iname" to ignore upper or lower case differences.
Find the files and open for editing:
$ find <directory path> -iname "<filename>" -exec micro '{}' \;Find text in files:
$ grep -[options] <text> <filename path>where option:
- -i = ignore upper or lower case differences
- -r = search sub-directories recursively
- -h = hide names of files preceding lines of output
- -w = search for exact text
- -c = count the number of matches
- -n = precede lines of output with the numbers of lines containing the text
- -v = show only lines not containing the text
- -l = list filenames only
- --colour = display the output in colour
Adjust disk space
Find duplicate files across several directories and replace duplicate files with hard links to save space:
$ sudo rdfind -makehardlinks true <directory path 1> <directory path 2>note: rdfind downloadable at https://rdfind.pauldreik.se/rdfind.1.html#lbAG.
Recover such harddisk space of deleted files not reported by "$ df":
$ cd /<directory name of the harddisk>
$ sudo dd if=/dev/zero of=tempfile
$ sudo rm tempfileEdit files
Text editor
$ sudo micro <filename path>or text editor
$ sudo nano <filename path>or GUI editor
$ sudo gedit <filename path>Shutdown and start up
Shutdown the system:
$ sudo shutdownShutdown and reboot the system:
$ sudo rebootStart a service:
$ sudo systemctl start <service name>or older method:
$ sudo service <service name> startor even older method:
$ sudo /etc/init.d/<service name> startRestart a service:
$ sudo systemctl restart <service name>or older method:
$ sudo service <service name> restartor even older method:
$ sudo /etc/init.d/<service name> restartStop a service:
$ sudo systemctl stop <service name>or older method:
$ sudo service <service name> stopor even older method:
$ sudo /etc/init.d/<service name> stopMount devices
(updated 18/7/2026)
Mount a single device, e.g. Network attached system, qnap2:
$ sudo mkdir /mnt/qnap2
$ sudo mount /mnt/qnap2Can use /media or any /<folder> instead of /mnt.
Remounting required after reboot.
Umount single device "/mnt/qnap2":
$ sudo umount -l /mnt/qnap2Check devices defined in the filesystem table file "fstab" to be mounted upon booting:
$ cat /etc/fstabCheck devices actually mounted (this would show more than those defined in "fstab"):
$ sudo mount -lSet up SSH keys to access remote computer
(section added, 29/7/2022)
(updated, 15/7/2026)
SSH keys
rsa key is older.
ed25519 key is newer
Generate public/private rsa key pair:
$ sudo ssh-keygen -t rsa
(or)
$ sudo ssh-keygen -t ed25519Enter file in which to save the key (/root/.ssh/<'id_rsa' or 'id_ed25519'>): <accept or change>
Skip entering passphrase if you do not want to use it upon logging in with ssh.
Skip it for use with remote drive to be automatically mounted.
If "sudo" is not used, the prompted file to save will be "/home/<your_user_name>/.ssh/<'id_rsa' or 'id_ed25519'>".
Use "sudo" because mounting remote drive would need "root".
If the file already exists, answer overwrite or not.
id_rsa (private key) and id_rsa.pub (public key) will actually be created.
or
id_ed25519 (private key) and id_ed25519.pub (public key) will actually be created.
Copy the public key to the remote computer connectable via <port_number>:
$ sudo ssh-copy-id -i /root/.ssh/id_rsa.pub -p <port_number> <login_name>@<remote_computer_address>
(or)
$ sudo ssh-copy-id -i /root/.ssh/id_ed25519.pub -p <port_number> <login_name>@<remote_computer_address>Enter password to the remote login name.
It will check whether the key has already existed.
Add "-f" if desired to force copy to overwrite an existing key:
$ ssh-copy-id -f -i /root/.ssh/id_rsa.pub -p <port_number> <login_name>@<remote_computer_address>
(or)
$ ssh-copy-id -f -i /root/.ssh/id_ed25519.pub -p <port_number> <login_name>@<remote_computer_address>Verify by logging in after successful copying:
$ sudo ssh -i /root/.ssh/id_rsa.pub -p <port_number> <login_name>@<remote_computer_address>
(or)
$ sudo ssh -i /root/.ssh/id_ed25519.pub -p <port number> <login_name>@<remote_computer_address>If login successful, you are at the command prompt of the remote computer and can execute commands there:
$ ls -la .ssh
(to show)
$ ls -la .ssh/authorized_keys
(which contains the copied public key)Enter "exit" after use.
Mount using a script file
To mount the remote computer (NAS qnap2) on /mnt/qnap2:
$ sudo micro setupsshfs.shEnter in the file:
sudo sshfs -o IdentityFile=/root/.ssh/id_rsa,port=12022,reconnect,ServerAliveInterval=15,ServerAliveCountMax=3,uid=1000,gid=1000,idmap=user,allow_other <login_name>@<remote_computer_address>:</remote/path> /mnt/qnap2No space permitted except as shown.
Save and exit.
Execute to mount:
$ sudo mkdir /mnt/qnap2
$ ./setupsshfs.sh
(to mount)
$ df -h
$ ls -ls /mnt/qnap2
(to verify)This method is stable but the mounted drive needs to be remounted after re-booting.
Mount using fstab
To make the mounting permanent, configure in /etc/fstab:
$ sudo micro /etc/fstabAdd the following line:
sshfs#<login_name>@<remote_computer_address>:</remote/path>: /mnt/qnap2 fuse IdentityFile=/root/.ssh/id_rsa,port=<port number>,reconnect,ServerAliveInterval=15,ServerAliveCountMax=3,uid=1000,gid=1000,idmap=user,allow_other,_netdev 0 0No space permitted except as shown.
Save and exit.
Execute to mount:
$ sudo systemctl daemon-reload
$ sudo mount /mnt/qnap2
(or)
$ sudo mount -a
$ df -h
(to see whether actually mounted on /mnt/qnap2)Try this to connect the mount if the remote computer was not connected when the computer was booted:
$ ls /mnt/qnap2However, this method is not very stable.
Mount using systemd service
The best is to configure it as a systemd service:
$ sudo micro /etc/systemd/system/mnt-qnap2.mountEdit as:
[Unit]
Description=SSHFS mount for QNAP2
After=network-online.target
Wants=network-online.target
[Mount]
What=sshfs#<login name>@<remote computer address>:</remote/path>
Where=/mnt/qnap2
Type=fuse
Options=IdentityFile=/root/.ssh/id_rsa,port=12022,reconnect,ServerAliveInterval=15,ServerAliveCountMax=3,uid=1000,gid=1000,idmap>
# no space permitted
[Install]
WantedBy=multi-user.target
[Service]
Restart=on-failure
RestartSec=120
TimeoutSec=10- TimeoutSec=10 → each sshfs attempt gives up after 10 seconds if the NAS isn’t reachable.
- RestartSec=120 → systemd waits 2 minutes before trying again.
Save and exit.
Execute to mount:
$ sudo systemctl daemon-reload
$ sudo systemctl enable mnt-qnap2.mount
$ sudo systemctl start mnt-qnap2.mount
$ sudo systemctl status mnt-qnap2.mountSee "setupsshfs.txt" in our administrator's home folder to see our company's exact settings for the above three methods.
Add or delete groups and users
Create new group:
$ sudo addgroup <new group name>Create new user, with a group and a home directory of the same name created if not already existing:
$ sudo adduser <new user name>To verify:
$ ls -lh /homeshows that the new directory has "drwxr-xr-x" permissions, i.e. "d" for directory with "rwx" owner permissions but "r-x" group and others' permissions.
Add a user to a group:
$ sudo adduser <user name> <group name>Delete user, and group of the same name, keeping the home directory:
$ sudo deluser <user name>Delete group:
$ sudo delgroup <group name>Change ownership
Change file or directory ownership:
$ chown -R <owner name>:<group name> <filename path>where:
- -R = recursively from and below if <filename> is a sub-directory
Change permissions
Change file or directory permissions:
$ chmod -R [ugoa][-+=][rwxXst] <filename path>where:
- -R = recursively from and below if <filename> is a <sub-directory>
- u=owner, g=group, o=others, a=all
- -+= mean minus, add or equal permissions
- r=read, w=write and delete, x=execute file or change directory into; Xst=for more special choices
- e.g. "u+rw" = add read and write permission to owner
An alternative form is:
$ chmod -R <ugo> <filename path>where:
- <ugo> is a 3 digit number where u=owner, g=group, o=others
- each digit can be:
- 0 for nothing
- 1 for execute "x"
- 2 for write "w"
- 3 = 1 + 2 = "wx"
- 4 for read "r"
- 5 = 4 + 1 = "rx"
- 6 = 4 + 2 = "rw"
- 7 = 4 + 2 + 1 = "rwx"
therefore:
- 666 = read and write permissions to all
- 777 = read, write and execute permissions to all
Change password
Change own password:
$ passwdChange other user 's password:
$ sudo passwd <other user's name>Recreate deleted user with specific UID
(section added, 3/2/2026)
To recreate deleted user account:
- Existing email folders: /home/xyz/Maildir
- User ID = 1234
- User name = xyz
Open Command Prompt.
Check the presence of directory xyz and the UID of the Maildir is 1234:
> ls -ls /home
> sudo ls -ld /home/xyz/MaildirRe-create full user account with the same UID and login shell:
> sudo useradd -u 1234 -d /home/xyz -s /bin/bash xyz- -u 1234 → sets the UID to 1234
- -d /home/xyz → sets the home directory
- -s /bin/bash → sets the default shell
Set the password for the re-created user:
> sudo passwd xyzEnter and confirm the password.
Fix ownership of the Maildir (if needed) if the Maildir or home directory files are not owned by UID 1234 after recreating the user:
> sudo chown -R xyz:xyz /home/xyzEnsure UID is 1234 and Maildir is accessible:
> id xyz
> sudo -u xyz ls /home/xyz/MaildirIf another user already exists with UID 1234, resolve that conflict first (either delete or re-assign that user).
Always back up the Maildir before making changes, just in case ownership or permissions get misapplied.
Recreate mailbox-only account
(section added, 3/2/2026)
To recreate deleted user account for mail delivery:
- Existing email folders: /home/xyz/Maildir
- User ID = 1234
- User name = xyz
Open Command Prompt.
Check the presence of directory xyz and the UID of the Maildir is 1234:
> ls -ls /home
> sudo ls -ld /home/xyz/MaildirRe-create mailbox-only account with the same UID but without login shell:
> sudo useradd -u 1234 -d /home/xyz -s /usr/sbin/nologin xyz-s /usr/sbin/nologin → prevents shell login
Set a locked password o nobody can log in interactively:
> sudo passwd -l xyzEnter and confirm the password.
Fix ownership of the Maildir (if needed) if the Maildir or home directory files are not owned by UID 1234 after recreating the user:
> sudo chown -R xyz:xyz /home/xyzEnsure UID is 1234 and Maildir is owned by xyz.
> id xyz
> ls -ld /home/xyz/MaildirIf another user already exists with UID 1234, resolve that conflict first (either delete or re-assign that user).
Always back up the Maildir before making changes, just in case ownership or permissions get misapplied.
Optional: Restrict home directory access if you want to prevent accidental browsing:
> sudo chmod 700 /home/xyz- Only xyz (and root) can access it.
The account will still be valid for mail delivery and IMAP/POP access using Postfix + Dovecot.
The nologin shell ensures it can’t be used for SSH or console login.
Create directories
Make new directory:
$ mkdir <directory>Make new directory and sub-directory in one go, "-p" means making parent directory also:
$ mkdir -p <directory>/<sub-directory>Remove files and directories
$ rmdir <directory path>Remove one empty sub-directory and its parent directory in one go:
$ rmdir /<parent directory>/<sub-directory>Remove all empty sub-directories and their parent directories in one go:
$ cd <directory>
$ find . -type d -empty -print -deleteIf directory is empty, print name then delete.
(added, 14/4/2022)
Remove file:
$ rm <filename path>Remove files and directories starting from and below sub-directory, even for empty sub-directory:
$ rm -r <directory path>List and change directories
List names of current directory contents, hiding entries starting with ".":
$ lsList current directory contents, with more detailed information:
$ ls -[options]where options
- l = list also permissions, owners, date and size
- a = list also entries starting with "."
- h = to be used in conjunction with "l", show file sizes in "K" or "M"
List other directory contents:
$ ls -[options] <directory path>Change working directory:
$ cd <directory path>Copy files and directories
(section added, 18/4/2022)
Copy a file within the same directory:
$ cp <source filename> <new filename>Copy a file across different directories, keeping the same filename:
$ cp <source directory>/<sub-directory>/<filename> <target directory>/<sub-directory>/.to give:
<target directory>/<sub-directory>/<filename>Copy a file across different directories, to a new filename:
$ cp <source directory>/<sub-directory>/<filename> <target directory>/<sub-directory>/<new filename>to give:
<target directory>/<sub-directory>/<new filename>Omit:
<source directory>/<sub-directory>/if copying files in the current directory.
Copy directories recursively, keeping the directory name:
$ cp -R <source directory>/<sub-directory A> <target directory>/.to give:
<target directory>/<sub-directory A>Copy directories recursively:
$ cp -R <source directory>/<sub-directory A> <target directory>/<sub-directory B>If sub-directory B exists, all files and directories under sub-directory A will be copied under sub-directory B.
If sub-directory B does not exist, it will be created, and all files and directories under sub-directory A will be copied under it.
Copy directories recursively (-R) keeping original attributes (-a) and showing verbose progress (-v):
$ cp -Rav <source directory>/<sub-directory A> <target directory>/<sub-directory B>Move files and directories
Backup a directory of files
(updated, 19/7/2026)
Archive (-a) all files under a sub-directory (A) and all sub-sub-directories underneath to the same sub-directory name under another sub-directory (B) keeping all the file attributes, symbolic links and time-stamps unchanged, preserving hard-links (-H) and displaying the progress verbosely (-v) and the numbers in human-readable format (-h):
$ sudo rsync -aHvh <source directory>/<sub-directory A> <target directory>/<sub-directory B>/to give:
<target directory>/<sub-directory B>/<sub-directory A>The command can be used repeatedly to update the files in sub-directory A in the new location. If the source files have not been changed, no over-writing copying will be done. This would save time and is better than the cp command.
Options:
-a = archive mode (permissions, symlinks, etc.)
-A = preserve ACL permissions
-H = use hard links
-X = preserve extended attributes
-v = verbose
--ignore-existing = skips files that already exist on the destination
--remove-source-files = remove from source
--dry-run = shows what would happen, but doesn’t actually copy.
--info=progress2 = gives a running count of files and progress
/A/B/ /C/D/means rsync folders and files under B/ to under D/.
/A/B /C/D/means rsync B to under D/.
Update firmware
(section added, 15/7/2026)
The server may notify that "n devices have a firmware upgrade available. Run `fwupdmgr get-upgrades` for more information."
Check available upgrades:
$ sudo fwupdmgr get-upgradesApply the upgrades:
$ sudo fwupdmgr updateReboot:
$ sudo rebootVerify no more upgrades:
$ sudo fwupdmgr get-devices
$ sudo fwupdmgr get-upgradesNote:
- Backup important data before updating (rare risk of instability).
- Keep using AC power while upgrading.
- Do not interrupt the update process — forced shutdowns can affect hardware.
- Some updates are staged and applied at the next reboot.
- Check vendor support: not all devices publish firmware via LVFS; unsupported ones require manual vendor tools.
- Logs: If something fails, check
/var/log/fwupd.logfor details.
Define time scheduled jobs
(section added, 18/7/2026)
However, Ubuntu does not have those files, meaning that all users can use cron.
List to show users permitted to use cron:
$ ls -l /var/spool/cron/crontabsTo enable user crontab:
Check where the user and "crontab" are in groups:
$ groupsIf not in, add user to the crontab group:
$ sudo usermod -aG crontab <user name>Log out and back in (or reboot) to apply group membership.
Try again:
$ crontab -eEnter as a simple test:
* * * * * echo "Cron test $(date)" >> ~/cron_test.logSave and exit. Within a minute or two, you should see lines appearing in ~/cron_test.log. That proves the user crontab is active.
Add user, alternatively:
$ sudo touch /etc/cron.allow
$ echo <user name> | sudo tee -a /etc/cron.allowGive a complete snapshot of all scheduled jobs on the system:
$ echo "=== User crontab ==="; crontab -l 2>/dev/null
$ echo "=== Root crontab ==="; sudo crontab -l
$ echo "=== /etc/cron.d ==="; sudo grep -r . /etc/cron.d/ 2>/dev/null
$ echo "=== cron.daily ==="; ls /etc/cron.daily
$ echo "=== cron.weekly ==="; ls /etc/cron.weekly
$ echo "=== cron.monthly ==="; ls /etc/cron.monthly
$ echo "=== anacrontab ==="; cat /etc/anacrontabShow what is actually running:
journalctl -u cron
(or)
grep CRON /var/log/syslogInstall Chrony
(section added, 19/7/2026)
Chrony is a modern time synchronization service that keeps the server’s system clock accurate by using the Network Time Protocol (NTP).
It has not been properly installed when Ubuntu 26.4 is freshly installed. The error message appears only when the server is starting up and is only seen when the starting up messages roll up the screen.
The following can verify and rectify as necessary:
Make sure chrony is installed:
$ sudo apt update
$ sudo apt install chrony -yEnsure the _chrony user/group exist:
$ sudo adduser --system --no-create-home --group --shell /usr/sbin/nologin _chronyFix ownership of chrony directories:
$ sudo chown -R _chrony:_chrony /var/lib/chrony
$ sudo mkdir -p /run/chrony
$ sudo chown _chrony:_chrony /run/chrony(Optional) Fix or disable keyfile:
$ sudo chown root:_chrony /etc/chrony/chrony.keys
$ sudo chmod 640 /etc/chrony/chrony.keysor comment out 'keyfile /etc/chrony/chrony.keys' in /etc/chrony/chrony.conf.
Reload systemd and restart chrony:
$ sudo systemctl daemon-reexec
$ sudo systemctl daemon-reload
$ sudo systemctl enable chrony
$ sudo systemctl restart chrony
$ sudo systemctl status chronyVerify synchronization:
$ chronyc tracking
$ chronyc sources