Linux CLI Cheatsheet
Below are some short snippets of code to help you perform day-to-day tasks in Linux. If you can't find what you are looking for, make sure to look at the BASH cheatsheet.
Related Posts
- BASH cheatsheet
- Linux CLI Audio Cheatsheet
- Docker CLI Cheatsheet
- Easily Parallelize Commands in Linux (Multiprocessing)
- Nmap Cheatsheet
Table of Contents
- JSON
- Filesystem
- File Manipulation
- Disk Management
- User Management
- Group Management
- Networking
- Output IPs
- Stop Processes That Are Using Port
- Blink NIC
- Output All Interfaces
- Output Specific Interface
- Bring Interface Down
- Bring Interface Up
- Network Manager - List DNS Nameservers For Interface
- Flush Systemd DNS Cache
- List DNS Servers Of Systemd Stub Resolver
- Get HTTP Status Code With Curl
- List Routes
- List Open Ports
- Bridges
- Time
- Misc
- Set Default Editor
- Hashes
- Copy CD To Disk
- Set File Timestamp
- Download File And Set Custom Name
- Get Time Taken For Command To Run
- CentOS - Check If Reboot Required
- Get Ubuntu Release Name
- Generate Random Passowrd
- Find Servers Fingerprint
- Regenerate OpenSSH Host Keys
- Change Keyboard Language
- Output Current Locale / Keymap
- References
JSON
Allo the following examples use jq
which can be installed with
sudo apt install jq -y
If you have some command or script that outputs in JSON, then it may not be in a readable format. To have it output to the terminal in a readable format, just pipe it to jq like so:
cat myJsonData.json | jq
If you then want that output to go to a file, do the following:
echo '[1,2,3,4,5,6,7,8,9,10]' | jq . > my-output-file.json
Filtering
If you wish to filter down to a specific sub block, then you can do this like so:
cat someComplicatedJson.json | jq '.primaryBlockKeyName.subBlockKey.tertiaryBlockKey
You can chain sub-blocks with .
as many times as you desire.
For more examples of using jq
, refer to the following:
Filesystem
Copy File(s) But Don't Overwrite
Sometimes you want to copy a file to another location, but are worries about the possibility of
overwriting something that already exists. If that's the case, use the -n
or --no-clobber
parameter.
cp -n $SOURCE $DEST
Move File(s) But Don't Overwrite
In the same situation as above, but for moving file(s).
mv -i
or
mv --interactive
cp -n
, this will propt you if you wish to overwrite files, whereas cp -n
will
just immediately exit with an error.
Get Folder Sizes
If you've ever completely filled a system to the point where you can't even install ncdu to track where all your storage is gone, you can get the size of all the folders at your current level by executing:
du -sh *
However, if you can use ncdu instead, that is a much better tool.
Move all Files of a Type To Own Folder
If you have a jumble of files with no apparent structure, perhaps from a backup, and want to move a ceratain file type (in this example PDFs) into their own directory then you can execute the following:
mkdir pdf
find . -name "*.pdf" -type f -exec /bin/mv {} ./pdf \;
Obviously if you just wanted to copy the files instead, use:
mkdir pdf
find . -name "*.pdf" -type f -exec /bin/cp {} ./pdf \;
List All Files Within All Subdirectories
find . -type f
If you wish to also list the directories:
find .
List All Files With Specific File Extensions
find ./ -type f \( -iname \*.jpg -o -iname \*.png \)
List all Files Over A Certain Size
The following command will recursively find individual files larger than [size]
in MB. This could
be useful for finding really large files to consider compressing/deleting.
find . -type f -size +[size]M
List all Files Over A Certain Age
The following command will find all the files over $NUM_DAYS in age.
find . -mtime +$NUM_DAYS
Validate Fstab
There are two possible options here:
sudo findmnt --verify --verbose
... or:
sudo mount --fake --all --verbose
The key thing here is the "fake" which causes everything to occur, except for the actual system call.
File Manipulation
Replace Text In Files (Sed)
I use variations of the sed command to manipulate config files for automated scripts
SEARCH="search text here"
REPLACE="replace text here"
FILEPATH="/path/to/file.conf"
sed -i "s;$SEARCH;$REPLACE;" $FILEPATH
If you want to replace an entire line, then just use .*
as shown below.
SEARCH="bind-address.*"
REPLACE="bind-address = $PRIVATE_IP"
FILEPATH="/etc/mysql/my.cnf"
sudo sed -i "s;$SEARCH;$REPLACE;" $FILEPATH
You can use [[:space:]]\+
when you don't know how many whitespaces or tabs there are. E.g.
SEARCH="datadir[[:space:]]\+= /var/lib/mysql"
REPLACE="datadir = /media/data/mysql"
FILEPATH="/etc/mysql/my.cnf"
sudo sed -i "s;$SEARCH;$REPLACE;" $FILEPATH
To replace an entire line that contains text that you are looking for in the middle of the line, you can use the following:
SEARCH="^.*\bYour pattern or sentence goes here\b.*$"
REPLACE="This will replace the entire line"
FILEPATH="$DIR/dump.sql"
sed -i "s;$SEARCH;$REPLACE;" $FILEPATH
Write To File
echo "my content here" | tee $FILEPATH
echo "my content here" > $FILEPATH
cat << EOF > [filepath]
[script content]
EOF
Write To File With Sudo Privileges
echo "my content here" | sudo tee $FILEPATH
cat << EOF | sudo tee $FILEPATH
[script content]
EOF
cat << EOF > [filepath]
[script content]
EOF
Output Both Stderr and Stdout To The Same File
It is quite often useful to have both stderr and stdout go out to the same output log file. This way when you come to read the log, the error output will be in the correct relative position to any normal output that came before/after it. I find this particularly useful for scheduled cron jobs:
[SOME_COMMAND_HERE] > file 2>&1
The above example will cause the log file to only contain output of the last call to the command.
If you wish to append to the file, rather than overwrite it, then one would need to use >>
like so:
[SOME_COMMAND_HERE] >> file 2>&1
Append To File
echo "my content here" >> $FILEPATH
Append To File (With Sudo Privs)
echo "my content here" | sudo tee -a $FILEPATH
cat << EOF | sudo tee -a $FILEPATH
[script content]
EOF
Split File Into Chunks
Let's say you have a massive text file, perhaps a giant log file. If that text file became unmanageable, and you wanted to split it into lot of smaller files that had up to x number of lines each, then you could do the following with the split command:
INPUT_FILE="my-file.txt"
OUTPUT_FILE_PREFIX="output-"
OUTPUT_FILE_EXTENSION=".txt"
MAX_LINES_PER_FILE=10000
split \
--verbose \
--numeric-suffixes \
--suffix-length=2 \
--lines=$MAX_LINES_PER_FILE \
--additional-suffix=$OUTPUT_FILE_EXTENSION \
$INPUT_FILE \
$OUTPUT_FILE_PREFIX
--suffix-length
accordingly.
E.g. 3 for up to 999 files.
Binary Split
Let's say you have a giant binary file, perhaps a gzipped version of your log or SQL file. You would likely want to split this based on bytes, rather than lines like so:
INPUT_FILE="dump.sql.gz"
OUTPUT_FILE_PREFIX="dump-"
OUTPUT_FILE_EXTENSION="sql.gz"
CHUNK_SIZE="512m"
split \
--numeric-suffixes \
--suffix-length=3 \
--bytes=$CHUNK_SIZE \
--additional-suffix=$OUTPUT_FILE_EXTENSION \
$INPUT_FILE \
$OUTPUT_FILE_PREFIX
Merge Split Files
If you wish to merge files together from perhaps splitting them earlier, then you can do this through cat like so:
cat dump-* > dump.sql.gz
Ordering
The example above that uses dump-*
does rely on your files listing in the correct order, which may vary depending on your locale settings.
If you want to specify the order, you could do the following:
cat file1 file2 file3 >> combined_file
Gzip A File
The following command will take the given file, and replace it with a gzipped one with the same name, but with a .gz
extension.
This is particularly useful for MySQL dumps and log files.
gzip myLogFile.txt
To then undo the operation do:
gzip --decompress myLogFile.txt.gz
Alternatively, the --uncompress
flag is a synonym that will do the same thing:
gzip --uncompress myLogFile.txt.gz
.gz
file with the decompressed file. If you want to keep the file, simply add the --keep
flag.
Disk Management
Get Utilization
df -h
Or you could install pydf for a simpler interface.
Secure Erase Disk
The best way to erase a disk is to use secure erase. For an SSD, this will reach areas that the other commands won't, and return it to peak performance.
Alternatively, you can use shred
shred -n 1 -vz /dev/sdb
... or use scrub
scrub -p dod /dev/sdb
... or you could use dd
.
Check SATA Connection of Drives
dmesg | grep -i ahci | grep -i --color Gbps
Check the SATA Connection Of Specific Drive
smartctl -a /dev/sda | grep "^SATA"
Get Block Size
sudo blockdev --getbsz /dev/sd[x]
The output will be in bytes, so typically this will be 4096 to represent a 4k block size.
List Block Devices
sudo lsblk
Example output:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 15G 0 disk
└─sda1 8:1 0 15G 0 part /
sdb 8:16 0 1000G 0 disk /mnt/data
sdc 8:32 0 1000G 0 disk
List Disk Labels
Using lsblk, we can get all of the details of the block devices, including their labels like so:
sudo lsblk -o name,mountpoint,label,size,uuid
Output When Disk Last Checked
The following command works on a disk or disk-partition basis to find out when it was last checked for errors:
DISK=/dev/sda1
sudo tune2fs -l $DISK | grep checked
DISK
variable.
User Management
Add User With Adduser
The simplest way to add users is to use the command below which will ask you a series of questions and set up their home directory.
sudo adduser [username]
Add User With Useradd
If you are wanting to add a user as part of a script, or just don't want to set up a home directory, you can use
sudo useradd [username]
In that format, it will create a user without a home directory or even a password, use the options
-m
to automatically create a home directory, and -p
to specify the encrypted password.
For example, the commands below will create a user called test
with a random password:
USER="test"
PASSWORD=`openssl rand -base64 16`
PASSWORD=${PASSWORD::-2}
ENCRYPTED_PASSWORD=$(openssl passwd -1 ${PASSWORD})
sudo useradd -m -p $ENCRYPTED_PASSWORD $USER
echo "Please log in with password: $PASSWORD"
Delete User
sudo deluser [user]
A full-blown command in which we specify the user ID, group ID, whether to create a home, and the shell to use would be:
sudo useradd \
--no-create-home \
--uid 1019 \
--gid 100 \
--shell /usr/sbin/nologin \
myUserName
Get User's ID
id --user $USERNAME
If you just want your own user ID, you can run:
id --user
Change User's ID
The following command would change the programster user to user ID 1026
sudo usermod -u 1026 programster
Get Users Primary Group ID
id --group $USER
Change Users Primary Group ID
You can also do the following to set a user's primary group:
usermod --gid primary_group_name programster
Add User To Group
sudo adduser $USERNAME $GROUPNAME
The adduser
command may not always be available. In such a scenario, you may wish to use:
sudo usermod \
--append $USER_NAME \
--groups $GROUP_NAME
usermod -a -G $GROUP_NAME $USER_NAME
, but I have
tested that this way round works, and I feel it is more memorable and intutitive.
Append User To Multiple Groups
If you want to append a user to multiple groups in one go, then you can do the following:
sudo usermod \
--append $USER_NAME \
--groups $GROUP1,$GROUP2,$GROUP3
Set User's Groups
If you want to specify the list of groups a user should be part of, which would append/remove the user from groups as appropriate to ensure they match the list, then you would do the following:
sudo usermod \
$USER_NAME \
--groups $GROUP1,$GROUP2,$GROUP3
Remove User From Group
sudo deluser $USERNAME $GORUPNAME
List Groups User Belongs To
groups $USER_TO_CHECK
Group Management
Create Group
sudo groupadd myGroupName
If you wish to specify the ID of the group, you would use:
sudo groupadd --gid 1003 myGroupName
Get Group's ID
The following will output the ID of the specified group:
cut -d: -f3 < <(getent group $GROUP_NAME)
Get Name Of Group From ID
Use the following to convert a group ID, to the name of the group
getent group $GROUP_ID | cut -d: -f1
List All Groups In System
The following command will list all the groups on the system.
cut -d: -f1 /etc/group | sort
Change Group's ID
groupmod --gid $DESIRED_GROUP_ID $GROUP_TO_CHANGE
For example, the following command would change the "admins" group to 1026.
sudo groupmod --gid 1026 admins
Rename Group
groupmod --new-name $NEW_GROUP_NAME $CURRENT_GROUP_NAME
e.g.
groupmod --new-name apacheUser www-data
Networking
Output IPs
hostname -I
If you want each IP on a newline, use the command below:
hostname -I | xargs | tr [:space:] '\n'
Stop Processes That Are Using Port
The following command will kill all processes that are using the port 1234.
lsof -ti:1234 | xargs kill -9
Blink NIC
If you have multiple NICs in a computer and want to know which one is which, you can make it blink.
The command below will make eth0
blink for 30 seconds.
ethtool -p eth0 30
Output All Interfaces
Networkctl
sudo networkctl status --all
IP Addr
ip addr
Output Specific Interface
If you just want details about a single interface, you can do either of the following:
Networkctl
INTERFACE="enp2s0"
sudo networkctl status $INTERFACE
IP Addr
INTERFACE="enp2s0"
ip addr show $INTERFACE
Bring Interface Down
DEVICE_NAME="eno1"
sudo ip link set dev $DEVICE_NAME down
Bring Interface Up
DEVICE_NAME="eno1"
sudo ip link set dev $DEVICE_NAME up
Network Manager - List DNS Nameservers For Interface
If you are using the network manager that comes bundled with distros like Ubuntu Desktop, then you may wish to list the DNS namservers your machine is set to use from all the different sources (DHCP etc).
DEVICE_NAME="wlp0s20f3"
nmcli device show $DEVICE_NAME | grep DNS
Flush Systemd DNS Cache
Use whichever of the two commans below works for your OS.
sudo resolvectl flush-caches
Alternative Flush Command
sudo systemd-resolve --flush-caches
List DNS Servers Of Systemd Stub Resolver
When your /etc/resolv.conf
file is set to the default of having your DNS set to 127.0.0.53
,
then this is using your local "stub resolver" as a cache, and you are actually querying some
other upstream DNS servers. To find out what these servers are, run the following command:
sudo resolvectl status
You should get some output similar to:
Global
Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
resolv.conf mode: stub
Link 2 (eno1)
Current Scopes: DNS
Protocols: +DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 192.168.0.1
DNS Servers: 192.168.0.1 fe80::6a2:22ff:fea0:e751%21880
DNS Domain: home
This IP address may not appear in the output if you were to run dig some.domain.com +trace
.
Get HTTP Status Code With Curl
If you need to find out what the HTTP status code returned from a URL is, you can do this using curl like so:
curl -s -o /dev/null -w "%{http_code}\n" https://some.website.com/
%{http_code}\n
is the important part, and the \n
is just to neatly print out the code on a separate line in the terminal. If using in a script, you probably want to take that out.
List Routes
You can run any of the following commands to show your routes:
ip route
ip route list
ip route show
List Open Ports
The command below will list the ports that your server is actively listening on for TCP and UDP connections, which is what most people are after when searching for this sort of thing:
ss --listening --numeric --tcp --udp
The shorthand for this is:
ss -lntu
-ltun
or -tunl
if you find that easier to remember.
For refernce, this uses the ss
command which stands for "socket statistics" in case you wish to search for
an online manual page.
Bridges
Show Bridges
sudo brctl show
Bring Bridge Down
sudo ip link set $BRIDGE_NAME down
Bring Bridge Up
sudo ip link set $BRIDGE_NAME up
Time
Get Timezone
date +'%:z %Z' # +01:00 BST
Set Timezone
sudo dpkg-reconfigure tzdata
Get Unix Timestamp
date +%s
Get Date
date +%d-%m-%Y # 29-12-2012
Misc
Set Default Editor
There are multiple ways one can do this. For a tempory solution for your current session, you can do:
export EDITOR=vim
To permanently make the change, you can run:
sudo update-alternatives --config editor
... or:
select-editor
Hashes
md5sum $FILEPATH | awk '{print $1}'
sha1sum $FILEPATH | awk '{print $1}'
sha256sum $FILEPATH | awk '{print $1}'
Copy CD To Disk
If you have a CD-Rom drive (remember those things?), and want to create an ISO version on your computer, you can do it like so:
dd if=/dev/cdrom of=filename.iso
Set File Timestamp
We all know that you can use touch $FILENAME
to update a file to say it was edited right now.
However, if you want to manually set a time that is in the past, you can use:
touch -d '1 June 2018 11:02' $FILENAME
Here is a little php snippet for programmatically setting time of files:
<?php
$filename = "test-php-file.txt"; // specify name for file to create/edit timestmap of
$timestamp = time() - (60*60); // set a unix timestamp here.
$dateString = date("d F Y H:i:s", $timestamp);
$cmd = "touch -d '{$dateString}' {$filename}";
shell_exec($cmd);
Download File And Set Custom Name
The following command will use wget to download a file, but set your own custom name for the file when it is downloaded.
wget --output-document="my-custom-filename.zip" http://my.domain.com/path-to-file
Get Time Taken For Command To Run
Sometimes it's useful to know how long a command takes. All you have to do is wrap it like so:
CMD="YOUR COMMAND GOES HERE"
utime="$( TIMEFORMAT='%lU';time ( $CMD ) 2>&1 1>/dev/null )"
echo "$utime"
CentOS - Check If Reboot Required
#!/bin/bash
LAST_KERNEL=$(rpm -q --last kernel | perl -pe 's/^kernel-(\S+).*/$1/' | head -1)
CURRENT_KERNEL=$(uname -r)
test $LAST_KERNEL = $CURRENT_KERNEL || echo REBOOT
Get Ubuntu Release Name
lsb_release -cs
This should output something like:
xenial
Generate Random Password
This is my favourite option from How-To-Geek: 10 Ways to Generate a Random Password from the Command Line
openssl rand -base64 32
If you need it to not contain special characters, you could use:
NUM_CHARACTERS=24
head /dev/urandom | tr -dc A-Za-z0-9 | head -c$NUM_CHARACTERS
... or if hexadecimal is ok (all lowercase):
NUM_CHARACTERS=24
openssl rand -hex $NUM_CHARACTERS
Find Server's Fingerprint
If you swap change a server around on an IP or domain name, you may see the following message:
ECDSA host key for dns.programster.org has changed and you have requested strict checking.
Host key verification failed.
If you wish to manually check what your server's fingerprint is, you can run the following command:
ssh-keygen -l -f /etc/ssh/ssh_host_ecdsa_key.pub
-l
tells ssh-keygen to "show fingerprint of specified public key file." and the -f
is
for specifying the filepath to the file we wish to work on.
Regenerate OpenSSH Host Keys
You may wish to regenerate your server's SSH identity if you are creating it from cloning, and receive messages like these:
This host key is known by the following other names/addresses:
~/.ssh/known_hosts:797: [hashed name]
~/.ssh/known_hosts:800: [hashed name]
~/.ssh/known_hosts:801: [hashed name]
To regenerate your server's SSH host key/identity run the following (on the server):
sudo rm /etc/ssh/ssh_host_* \
&& sudo dpkg-reconfigure openssh-server \
&& sudo systemctl restart ssh
Change Keyboard Language
KEYMAP="gb"
sudo localectl set-keymap $KEYMAP
sudo localectl list-keymaps
If you get an error stating that your keymap is not installed, I worked around this by installing and running console-setup like so:
sudo apt install console-setup
sudo dpkg-reconfigure console-setup
... which resolved the issue, and allowed me to set the console to use a larger font.
Output Current Locale / Keymap
sudo localectl
References
- Nixcraft - Linux Command To Find SATA Link Speed
- Unix & Linux - How to measure time of program execution and store that inside a variable
- Nixcraft - How to Change a USER and GROUP ID on Linux For All Owned Files
- Unix And Linux - How to change primary group?
- Stack Overflow - Linux how to copy but not overwrite?
- Unix & Linux - How to use find command to search for multiple extensions
- StackOverflow - What command do I use to see what the ECDSA key fingerprint of my server is?
- Unix & Linux - List partition labels from the command line
- ServerFault - How do you validate fstab without rebooting?
- How To: Ubuntu / Debian Linux Regenerate OpenSSH Host Keys
- SuperUser - Getting curl to output HTTP status code?
- Linuxize - How to Redirect stderr to stdout in Bash
First published: 16th August 2018