Sign In
Sign In

How to Use the grep Command in Linux

How to Use the grep Command in Linux
Hostman Team
Technical writer
Linux
27.09.2024
Reading time: 12 min

The grep command is built into many Linux distributions. It runs a utility that searches either for a specific file containing the specified text or for a specific line within a file containing the given characters.

The name "grep" stands for "global regular expression print." Some developers casually say "to grep" something, meaning searching for a specific regular expression in a large set of files.

The command can accept directories with files to search and the text output of other commands, filtering it accordingly.

In this article, we will take a detailed look at using the grep command:

  • We will break down the grep command syntax;

  • Test the functionality of regular expressions;

  • Try various options while using the command;

  • Perform searches both within a single file and across entire directories;

  • Learn how to include and exclude specific files from the search.

Command Syntax

The command is structured as follows:

grep [flags] pattern [<path to directory or file>]
  • First, specify the flags to configure the search and output behavior.

  • Next, provide a regular expression, which is used to search for text.

  • As the last argument, enter the path to a file or a directory where the search will be performed. If a directory is specified, the search is performed recursively.

Instead of files and directories, you can also pass the output of another command as input:

another_command | grep [flags] pattern

This helps filter out the most important information from less relevant data during the output from other programs.

Regular expressions are the core of the grep command. They are essential for creating search patterns. Regular expressions have two levels—Basic Regular Expressions (BRE) and Extended Regular Expressions (ERE). To enable the latter, you need to use the -E flag.

The nuances of using the grep utility are best understood through practical examples. We will sequentially review the main methods of searching for strings within files.

Creating Text Files

Before running any searches, let’s prepare the environment by setting up a few text files that we’ll use with the grep utility.

Directory for Files

First, we’ll create a separate folder to hold the files where we’ll search for matches.

Create a directory:

mkdir files

Then navigate into it:

cd files

Text Files

Let’s create a couple of files with some text:

nano english.txt

This file will contain an excerpt from Jane Austen’s Pride and Prejudice along with some additional text to demonstrate the search commands:

However little known the feelings or views of such a man may be on his first entering a neighbourhood, this truth is so well fixed in the minds of the surrounding families, that he is considered as the rightful property of some one or other of their daughters.
The surrounding was quite overwhelming
Walking and talking became the main activities of the evening

Additionally, let’s create another text file named sample.txt:

nano sample.txt

Add the following content:

Line 1: This is the first line.
Line 2: Here we see the second line ending with something interesting.
Line 3: Another normal line follows here.
Line 4: This line is captivating and worth noting.
Line 5: The pattern we seek is right here, at the ending.
Line 6: Yet another normal line to keep the flow.
Line 7: Ending this line with something worth checking.
Line 8: A concluding thought here.
Line 9: This line does not end as the others.
Line 10: Just a regular line here.

File with Code

Next, let’s add a file that contains some simple JavaScript code:

nano code

Here’s the content:

const number1 = 2;
const number2 = 4;
const sum = number1 + number2;
console.log('The sum of ' + number1 + ' and ' + number2 + ' is ' + sum);

Listing Created Files

Finally, let’s check the created files:

ls

The console should display:

code  english.txt  sample.txt

Perfect! These are the files we’ll use to test the functionality of the grep command.

Simple Match

Let's try to find all instances of the word "the" in the first file:

grep 'the' english.txt

The console will display the found elements, with all occurrences of "the" highlighted in red.

However, there’s an issue—grep also highlighted parts of words like "other" and "their," which are not standalone articles.

To find only the article "the," we can use the -w flag. This flag ensures that the search looks for whole words only, without matching subsets of characters within other words:

grep -w 'the' english.txt

Now the terminal will highlight only those instances of "the" that are not part of another word.

End of Line

We can make the regular expression more complex by adding a special operator. For example, we can find lines that end with a specific set of characters:

grep 'ing$' english.txt

The console will display only those lines that contain the specified matches, with them highlighted in red.

This approach helps refine searches, especially when focusing on precise patterns within text.

Search Flags

Searching with Extended Regular Expressions (-E)

You can activate extended regular expressions by specifying the -E flag. The extended mode adds several new symbols, making the search even more flexible.

  • +
    The preceding character repeats one or more times.

  • ?
    The preceding character repeats zero or more times.

  • {n, m}
    The preceding character repeats between n and m times.

  • |
    A separator that combines different patterns.

Here’s a small example of using extended regular expressions:

grep -E '[a-z]+ing$' ./*

This command specifies that the string should end with "ing," which must be preceded by one or more lowercase letters.

The output would be something like:

./english.txt:The surrounding was quite overwhelming.
./english.txt:Walking and talking became the main activities of the evening.

Regular expressions, the foundation of the grep utility, are a versatile formal language used across various programming languages and operating systems.

Therefore, this guide covers only a portion of their capabilities.

Line Number (-n)

The -n flag can be used to display line numbers alongside the found matches:

grep -n 'ing$' english.txt

The output will be:

4:The surrounding was quite overwhelming.
5:Walking and talking became the main activities of the evening.

Case-Insensitive Search (-i)

The -i flag allows you to search for matches without considering the case of the characters:

grep -i 'the' english.txt

The output will be:

However little known the feelings or views of such a man may be on his first entering a neighbourhood,  
this truth is so well fixed in the minds of the surrounding families,  
that he is considered as the rightful property of some one or other of their daughters.  
The surrounding was quite overwhelming.
Walking and talking became the main activities of the evening.

If we didn’t use this flag, we would only find the matches with the exact case:

grep 'the' english.txt
However little known the feelings or views of such a man may be on his first entering a neighbourhood,  
this truth is so well fixed in the minds of the surrounding families,  
that he is considered as the rightful property of some one or other of their daughters.  
Walking and talking became the main activities of the evening.

This shows how adjusting flags can refine your search results with grep.

Search for Whole Words (-w)

Sometimes, you need to find only whole words rather than partial matches of specific characters. For this, the -w flag is used.

We can modify the previous search by using both the -i and -w flags simultaneously:

grep -iw 'the' english.txt

The output will contain lines with full matches of the word "the" in any case:

However little known the feelings or views of such a man may be on his first entering a neighbourhood,  
this truth is so well fixed in the minds of the surrounding families,  
that he is considered as the rightful property of some one or other of their daughters.  
The surrounding was quite overwhelming.  
Walking and talking became the main activities of the evening.

Inverted Search (-v)

You can invert the search results, which means it will display only those lines that do not contain the specified matches:

grep -v 'the' english.txt

For clarity, you can include line numbers:

grep -vn 'the' english.txt

The console output will be:

4:The surrounding was quite overwhelming.

As you can see, lines containing the word "the" are excluded from the results.

The line "The surrounding was quite overwhelming." is included because grep -v 'the' performs a case-sensitive search by default. Since the search pattern 'the' is in lowercase, it does not match the uppercase "The" at the beginning of the sentence. As a result, this line is not excluded from the output.

 

To exclude lines with any case of "the," you would need to use the -i flag along with -v:

 

grep -vin 'the' english.txt

 

This command would then exclude lines containing "The" as well.

Multiple Regular Expressions (-e)

You can use multiple regular expressions in a single search by specifying each pattern after the -e flag:

grep -e 'ing$' -e 'surround' ./*

This command is equivalent to running the two searches sequentially:

grep 'ing$' ./*
grep 'surround' ./*

The combined output will include matches from both patterns.

Recursive Search (-r)

Let’s move up one level to the root directory:

cd

Now, let’s perform a recursive search in the root directory:

grep -r 'ing$' ./

The grep command will find matches in the directory one level down—in the folder containing text files. The output will be as follows:

./files/english.txt:The surrounding was quite overwhelming.
./files/english.txt:Walking and talking became the main activities of the evening.

Note the file path in the results; it now includes the subdirectory's name.

Let’s navigate back to the folder with the files:

cd files

Extended Output (-A, -B, -C)

In some cases, it’s important to extract not only the line with the matching pattern but also the lines surrounding it. This helps to understand the context better.

After Match Lines (-A)

Using the -A flag, you can specify the number of lines to display AFTER the line with the found match. For example, let's display one line after each match of lines ending with "ending":

grep -A1 'ending' sample.txt

The output will be:

Line 2: Here we see the second line ending with something interesting.
Line 3: Another normal line follows here.
--
Line 5: The pattern we seek is right here, at the ending.
Line 6: Yet another normal line to keep the flow.

Before Match Lines (-B)

Using the -B flag, you can specify the number of lines to display BEFORE the line with the found match:

grep -B1 'ending' sample.txt

The output will be:

Line 1: This is the first line.
Line 2: Here we see the second line ending with something interesting.
--
Line 4: This line is captivating and worth noting.
Line 5: The pattern we seek is right here, at the ending.

Context Lines (-C)

Using the -C flag, you can specify the number of lines to display both BEFORE and AFTER the line with the found match:

grep -C1 'ending' sample.txt

The output will be:

Line 1: This is the first line.
Line 2: Here we see the second line ending with something interesting.
Line 3: Another normal line follows here.
Line 4: This line is captivating and worth noting.
Line 5: The pattern we seek is right here, at the ending.
Line 6: Yet another normal line to keep the flow.

Output Only the Count of Matching Lines (-c)

The -c flag allows you to display only the number of matches instead of showing each matching line:

grep -c 'ing$' ./*

The console output will be:

./code:0
./english.txt:2
./sample.txt:4

As you can see, even the absence of matches is displayed in the terminal. In this case, there are three matches in the english.txt file and three in the sample.txt file, while no matches are found in code.

Limited Output (-m)

You can limit the output to a specific number of matching lines using the -m flag. The number of lines is specified immediately after the flag without a space:

grep -m1 'ing$' ./*

Instead of displaying all matches, the console will show only the first occurrence:

./english.txt:The surrounding was quite overwhelming.
./sample.txt:Line 2: Here we see the second line ending with something interesting.

This allows you to shorten the output, displaying only the specified number of matches, which can be useful when working with large datasets.

Searching in Multiple Files

Searching in Directories

To search across multiple directories, you can specify a pattern that includes the possible paths of the files you're looking for:

grep 'su' ./*

The terminal will display combined output with matching lines from multiple files:

./code:const sum = number1 + number2;
./code:console.log('The sum of ' + number1 + ' and ' + number2 + ' is ' + sum);
./english.txt:However little known the feelings or views of such a man may be on his first entering a neighbourhood,  
./english.txt:this truth is so well fixed in the minds of the surrounding families,  
./english.txt:The surrounding was quite overwhelming.

Notice that when searching in a directory, the console output includes the file path for each matching line, distinguishing it from searches within a single file.

Including and Excluding Files

When searching in directories, you can include or exclude specific files using the --include and --exclude flags.

For example, you can exclude the English text file from the previous search:

grep --exclude 'english.txt' 'su' ./*

The terminal will then display:

./code:const sum = number1 + number2;
./code:console.log('The sum of ' + number1 + ' and ' + number2 + ' is ' + sum);

You could achieve the same result by including only the code file in the search:

grep --include 'code' 'su' ./*

It’s important to understand that the file names used in --include and --exclude are also treated as regular expressions.

For instance, you can do the following:

grep --include '*s*1' ' ' ./*

This command searches for a space character only in files that contain the letter "s" and end with the digit "1" in their names.

Excluding Directories

In addition to excluding files, you can exclude entire directories from your search.

First, let’s move up one level:

cd

Now perform a recursive search in the current directory while excluding specific folders using the --exclude-dir option:

grep --exclude-dir='files' -R 'su' ./*

In this case, the folder named files will be excluded from the search results.

Let’s navigate back to the folder with the files:

cd files

Conclusion

In most UNIX-like systems, the grep command provides powerful capabilities for searching text within the file system.

Additionally, grep is well-suited for use within Linux pipelines, enabling it to process external files and the output of other console commands. This flexibility is achieved through using regular expressions and various configurable search flags.

By combining all the features of this utility, you can tackle a wide range of search tasks. In many ways, grep is like a "Swiss Army knife" for finding information in Linux-based operating systems.

You can get a managed linux vps hosting on Hostman. 

Linux
27.09.2024
Reading time: 12 min

Similar

Linux

NATS Installation, Configuration, and Usage Guide

NATS is a simple, fast, and lightweight message broker written in the Go programming language. NATS has several data organization features: Key-Value: Data within NATS is stored in "key-value" format, where each key corresponds to a specific value. Subjects: Data within NATS is organized into so-called "Subjects," which are named channels for message transmission. Subjects can be divided into segments with hierarchical structures. Publish/Subscribe (Pub/Sub): Data within NATS is transmitted through a model where "Publishers" send messages to "Subjects," and "Subscribers" can subscribe to these "Subjects" to receive messages. Unlike many other message brokers (such as Apache Kafka or RabbitMQ), NATS has several significant advantages: Simplicity and Performance: Messages are transmitted through a simple and fast Pub/Sub protocol. When a message is sent to a subject, all subscribers immediately receive it. This minimizes delays and other overhead costs. Stateless: Information about the state of messages transmitted through the broker is not stored within it, nor is data about subject subscribers. The absence of complex state synchronization allows NATS to scale easily. No Default Queues: In standard configuration, NATS does not form message queues. This is important in cases where data timeliness is more important than persistence. It also eliminates queue management overhead. Reliable Protocol: Messages within the broker are transmitted using the "at-most-once delivery" method. This means a subscriber either receives a message once or not at all. This increases communication reliability and prevents duplicate responses to forwarded messages. Thus, NATS enables building fast and reliable communication between multiple different services. In this guide, we will thoroughly examine how to install, configure, and correctly use NATS in projects running on Ubuntu 22.04. Downloading NATS Package Updates Before installation, it's recommended to update the list of available repositories in the system: sudo apt update Downloading the Archive Next, you need to manually download the ZIP archive with NATS from its official GitHub repository: wget https://github.com/nats-io/nats-server/releases/download/v2.10.22/nats-server-v2.10.22-linux-amd64.zip After the download is complete, you can check the file list: ls Among them will be the NATS archive: nats-server-v2.10.22-linux-amd64.zip  resize.log  snap Extracting the Archive Next, install the package that performs ZIP archive extraction: sudo apt install unzip -y The -y flag is added so that the installer automatically answers 'yes' to all questions. Now extract the NATS archive using the installed extractor: unzip nats-server-v2.10.22-linux-amd64.zip Check the file list: ls As you can see, a new folder with the archive contents has appeared: nats-server-v2.10.22-linux-amd64  nats-server-v2.10.22-linux-amd64.zip  resize.log  snap We no longer need the archive, so delete it: rm nats-server-v2.10.22-linux-amd64.zip Installing NATS Server Installation Let's look at the contents of the created folder: ls nats-server-v2.10.22-linux-amd64 Inside it is the main directory with the NATS server: LICENSE  nats-server  README.md This is what we need to copy to the system catalog with binary files: sudo mv nats-server-v2.10.22-linux-amd64/nats-server /usr/local/bin/ After copying, you need to set the appropriate access permissions: sudo chmod +x /usr/local/bin/nats-server The folder with NATS contents, like the archive, can now also be deleted: rm nats-server-v2.10.22-linux-amd64 -R Server Verification Let's verify that the NATS server is installed by requesting its version: nats-server -v A similar output should appear in the console terminal: nats-server: v2.10.22 However, this command doesn't start the server; it only returns its version. You can start the server as follows: nats-server [3704] 2024/11/07 02:59:53.908362 [INF] Starting nats-server [3704] 2024/11/07 02:59:53.908623 [INF] Version: 2.10.22 [3704] 2024/11/07 02:59:53.908669 [INF] Git: [240e9a4] [3704] 2024/11/07 02:59:53.908701 [INF] Name: NC253DIPURNIY4HUXYQYC5LLAFA6UZEBKUIWTBLLPSMICFH3E2FMSXB7 [3704] 2024/11/07 02:59:53.908725 [INF] ID: NC253DIPURNIY4HUXYQYC5LLAFA6UZEBKUIWTBLLPSMICFH3E2FMSXB7 [3704] 2024/11/07 02:59:53.909430 [INF] Listening for client connections on 0.0.0.0:4222 [3704] 2024/11/07 02:59:53.909679 [INF] Server is ready In this case, the server starts with binding to the console terminal, not as a background service. Therefore, to return to command input mode, you need to press Ctrl + C. NATS Configuration Creating a Configuration File After the broker server is started, you can create a separate directory for the NATS configuration file: mkdir /etc/nats And then create the configuration file itself: sudo nano /etc/nats/nats-server.conf Its contents will be as follows: cluster { name: "test-nats" } store_dir: "/var/lib/nats" listen: "0.0.0.0:4222" Specifically in this configuration, the most basic parameters are set: name: Server name within the NATS cluster store_dir: Path to the directory where working data will be stored listen: IP address and port that the NATS server will occupy Creating a Separate User For all directories related to NATS, you need to create a separate user: useradd -r -c 'NATS service' nats Now create the directories specified in the configuration file: mkdir /var/log/nats /var/lib/nats For each directory, assign appropriate access permissions to the previously created user: chown nats:nats /var/log/nats /var/lib/nats Creating a Background Service Earlier we started the NATS server with binding to the console terminal. In this case, when exiting the console, the server will stop working. To prevent this, you need to create a file for the systemd service: sudo nano /etc/systemd/system/nats-server.service Its contents will be: [Unit] Description=NATS message broker server After=syslog.target network.target [Service] Type=simple ExecStart=/usr/local/bin/nats-server -c /etc/nats/nats-server.conf User=nats Group=nats LimitNOFILE=65536 ExecReload=/bin/kill -HUP $MAINPID Restart=on-failure [Install] WantedBy=multi-user.target This file contains several key parameters: Description: Short description of the service ExecStart: NATS server startup command with the configuration file explicitly specified User: Name of the user created for NATS Now we need to set up the service to start up at boot:  systemctl enable nats-server --now The --now flag immediately starts the specified service. The corresponding message will appear in the console: Created symlink /etc/systemd/system/multi-user.target.wants/nats-server.service → /etc/systemd/system/nats-server.service. Now check the status of the running service: systemctl status nats-server If the NATS server service started successfully, the corresponding message will be among the console output: ... Active: active (running) ... Connecting to NATS You can connect to the NATS server through the console terminal and thus perform message broker testing. For example, publish messages or subscribe to subjects. Client Installation To manage the NATS server, you need to install the natscli client. You can download it from the official GitHub repository: wget https://github.com/nats-io/natscli/releases/download/v0.1.5/nats-0.1.5-amd64.deb After this, the downloaded archive can be extracted and installed: dpkg -i nats-0.1.5-amd64.deb The archive itself can be deleted as it's no longer needed: rm nats-0.1.5-amd64.deb Sending Messages Now you can send a message to the message broker: nats pub -s 127.0.0.1 "someSubject" "Some message" In this command, we send the message "Some message" to the subject "someSubject" to the message broker running on IP address 127.0.0.1 and located on the standard NATS port - 4222. After this, information about the sent data will appear in the console terminal: 10:59:51 Published 12 bytes to "someSubject" Reading Messages Currently, no one will see this message since there's no agent subscribed to the specified subject. We can simulate a service subscribed to the subject and reading messages using another SSH session. To do this, you need to open another console terminal, connect to the remote machine, and subscribe to the previously specified subject: nats sub -s 127.0.0.1 "someSubject" A message about successful subscription will appear in the terminal: 11:11:10 Subscribing on someSubject Now repeat sending the message from the first terminal: nats pub -s 127.0.0.1 "someSubject" "Some message" Information about the new message will appear in the second terminal: [#1] Received on "someSubject" Some message Let's send another message from the first terminal: nats pub -s 127.0.0.1 "someSubject" "Some message again" The corresponding notification will appear in the second terminal: [#2] Received on "someSubject" Some message again Note that the console output of received messages has numbering in square brackets. Go Program + NATS Let's create a small program in the Golang programming language using the NATS message broker. Installing Go First, you need to ensure that the Go compiler is installed in the system: go version If the following message appears in the console terminal, then Go is not yet installed: Command 'go' not found, but can be installed with: snap install go # version 1.23.2, or apt install golang-go # version 2:1.18~0ubuntu2 apt install gccgo-go # version 2:1.18~0ubuntu2 See 'snap info go' for additional versions. In this case, you need to download it as an archive from the official website: wget https://go.dev/dl/go1.23.3.linux-amd64.tar.gz -O go.tar.gz And then extracted: sudo tar -xzvf go.tar.gz -C /usr/local As we no longer need the downloaded archive, we can delete it: rm go.tar.gz Next, you need to add the Go compiler to the PATH variable so it can be called from the console terminal: echo export PATH=$HOME/go/bin:/usr/local/go/bin:$PATH >> ~/.profile Then apply the changes: source ~/.profile Verify that Go is installed successfully by requesting its version: go version You will see a similar output: go version go1.23.3 linux/amd64 Creating a Project Let's create a separate folder for the Golang program: mkdir nats_go Then navigate to it: cd nats_go And initialize the Go project: go mod init nats_go Installing the Module After project initialization, you need to install the NATS client from the official GitHub repository. You don't need to download anything manually; it's enough to use the built-in Golang function: go get github.com/nats-io/nats.go/ Writing Code Now you can create a file with the program code: nano nats_go.go Its contents will be: package main import ( "fmt" // module for working with console "os" // module for working with system functions "time" // module for working with time "github.com/nats-io/nats.go" // module for working with NATS server ) func main() { // get NATS server address from environment variable url := os.Getenv("NATS_URL") // if there's no address in environment variable, use default address if url == "" { url = nats.DefaultURL } // connect to NATS server nc, _ := nats.Connect(url) // defer message broker cleanup until main() function completion defer nc.Drain() // send message to subject without subscribers to ensure it disappears nc.Publish("people.philosophers", []byte("Hello, Socrates!")) // subscribe to all sub-subjects in "people" subject sub, _ := nc.SubscribeSync("people.*") // extract message msg, _ := sub.NextMsg(10 * time.Millisecond) // output message status (it's not there because it was sent before subscribing to subjects) fmt.Printf("No message? Answer: %v\n", msg == nil) // send message to "philosophers" sub-subject of "people" subject nc.Publish("people.philosophers", []byte("Hello, Socrates!")) // send message to "physicists" sub-subject of "people" subject nc.Publish("people.physicists", []byte("Hello, Feynman!")) // extract message and output to console msg, _ = sub.NextMsg(10 * time.Millisecond) fmt.Printf("Message: %q in subject %q\n", string(msg.Data), msg.Subject) // extract message and output to console msg, _ = sub.NextMsg(10 * time.Millisecond) fmt.Printf("Message: %q in subject %q\n", string(msg.Data), msg.Subject) // send message to "biologists" sub-subject of "people" subject nc.Publish("people.biologists", []byte("Hello, Darwin!")) // extract message and output to console msg, _ = sub.NextMsg(10 * time.Millisecond) fmt.Printf("Message: %q in subject %q\n", string(msg.Data), msg.Subject) } Now you can run the created program: go run . The program's output will appear in the console terminal: No message? Answer: true Message: "Hello, Socrates!" in subject "people.philosophers" Message: "Hello, Feynman!" in subject "people.physicists" Message: "Hello, Darwin!" in subject "people.biologists" Python Program + NATS As another example, let's consider using the NATS message broker in the Python programming language. First, you need to ensure that the Python interpreter is installed in the system by requesting its version: python --version The corresponding message will appear in the console: Python 3.10.12 Note that this guide uses Python version 3.10.12. Installing PIP To download the NATS client for Python, you first need to install the PIP package manager: apt install python3-pip -y The -y flag helps automatically answer positively to all questions during installation. Installing the Client Now you can install the NATS client for Python: pip install nats-py Creating a Project For the Python program, let's create a separate directory: mkdir nats_python And navigate to it: cd nats_python Writing Code Let's create a file with the program code: nano nats_python.py Its contents will be: import os import asyncio # import NATS client import nats from nats.errors import TimeoutError # get environment variable containing NATS server address servers = os.environ.get("NATS_URL", "nats://localhost:4222").split(",") async def main(): # connect to NATS server nc = await nats.connect(servers=servers) # send message to subject without subscribers to ensure it disappears await nc.publish("people.philosophers", "Hello, Socrates!".encode()) # subscribe to all sub-subjects in "people" subject sub = await nc.subscribe("people.*") try: # extract message msg = await sub.next_msg(timeout=0.1) except TimeoutError: pass # send message to "philosophers" sub-subject of "people" subject await nc.publish("people.philosophers", "Hello, Socrates!".encode()) # send message to "physicists" sub-subject of "people" subject await nc.publish("people.physicists", "Hello, Feynman!".encode()) # extract message and output to console msg = await sub.next_msg(timeout=0.1) print(f"{msg.data.decode('utf-8')} in subject {msg.subject}") # extract message and output to console msg = await sub.next_msg(timeout=0.1) print(f"{msg.data.decode('utf-8')} in subject {msg.subject}") # send message to "biologists" sub-subject of "people" subject await nc.publish("people.biologists", "Hello, Darwin!".encode()) # extract message and output to console msg = await sub.next_msg(timeout=0.1) print(f"{msg.data.decode('utf-8')} in subject {msg.subject}") # unsubscribe from subjects await sub.unsubscribe() # clean up message broker await nc.drain() if __name__ == '__main__': asyncio.run(main()) Now you can run the created script: python nats_python.py The result of its operation will be the following output in the console terminal: Hello, Socrates! in subject people.philosophers Hello, Feynman! in subject people.physicists Hello, Darwin! in subject people.biologists As you can notice, the logic of this Python program doesn't differ from the logic of the Go program. The difference is only in the syntactic constructions of the specific programming language. Conclusion This guide examined the use of the NATS message broker in sequential stages: Downloading and installing NATS from the official GitHub repository Minimal NATS server configuration Managing the NATS server through the console terminal client Using NATS in a Golang program Using NATS in a Python program We downloaded all NATS clients used in this guide (for terminal, Go, and Python) from the official NATS repository on GitHub, which hosts modules and libraries for all programming languages supported by NATS. You can find more detailed information about configuring and using NATS in the official documentation. There are also many examples of using NATS in different programming languages.
24 June 2025 · 13 min to read
Linux

Listing and Deleting Iptables Firewall Rules

The iptables application is a firewall essential for securely working with network resources on the Linux platform. While there is extensive material dedicated to configuring iptables, we will focus on a few specific tasks: how to view rule lists, delete unnecessary rules, flush chains, and clear the packet count and byte size counters.  We do not recommend modifying the SSH connection on port 22 unless you are absolutely sure of your actions, as you might accidentally block remote access to your test host. In this guide, we will use a Hostman cloud server running Ubuntu. The setup process will be similar on CentOS and Debian. Before proceeding, make sure you have a user with sudo privileges. Viewing Rules In iptables, you can view the rules set by default or by a previous administrator. Execute the command: sudo iptables -S The result will be displayed like this: -P INPUT DROP -P FORWARD DROP -P OUTPUT ACCEPT -N ICMP -N TCP -N UDP -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -m conntrack --ctstate INVALID -j DROP -A INPUT -p udp -m conntrack --ctstate NEW -j UDP -A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j TCP -A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable -A INPUT -p tcp -j REJECT --reject-with tcp-reset -A INPUT -j REJECT --reject-with icmp-proto-unreachable -A TCP -p tcp -m tcp --dport 22 -j ACCEPT Viewing a Specific Chain This function is used when you want to exclude a specific chain (e.g., INPUT, OUTPUT, TCP, etc.) from the general output. Specify the chain name after the -S option. Example: sudo iptables -S TCP The result: -N TCP -A TCP -p tcp -m tcp --dport 22 -j ACCEPT View Rules as a Table This method is convenient for comparing different rules. The tabular format is built into the utility and is activated using the -L option. Enter: sudo iptables -L You can also limit the output to a specific chain: sudo iptables -L INPUT Sample output: Chain INPUT (policy DROP) target prot opt source destination ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED ACCEPT all -- anywhere anywhere DROP all -- anywhere anywhere ctstate INVALID UDP udp -- anywhere anywhere ctstate NEW TCP tcp -- anywhere anywhere tcp flags:FIN,SYN,RST,ACK/SYN ctstate NEW ICMP icmp -- anywhere anywhere ctstate NEW REJECT udp -- anywhere anywhere reject-with icmp-port-unreachable REJECT tcp -- anywhere anywhere reject-with tcp-reset REJECT all -- anywhere anywhere reject-with icmp-proto-unreachable Explanation: target – action taken when a packet matches the rule (e.g., ACCEPT, DROP, redirect to another chain). prot – protocol used (UDP, TCP, ALL). opt – IP options, if any. source – source IP/subnet (e.g., "anywhere" = from anywhere). destination – destination IP/subnet. The last column (without a header) contains additional rule parameters like port numbers or connection states. Viewing Packet and Byte Counters You can also display the packet and total byte count per rule. This is useful for estimating traffic by rule. Available with -L and -v: sudo iptables -L INPUT -v Sample output: Chain INPUT (policy DROP 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 284K 42M ACCEPT all -- any any anywhere anywhere ctstate RELATED,ESTABLISHED 0 0 ACCEPT all -- lo any anywhere anywhere 0 0 DROP all -- any any anywhere anywhere ctstate INVALID 396 63275 UDP udp -- any any anywhere anywhere ctstate NEW 17067 1005K TCP tcp -- any any anywhere anywhere tcp flags:FIN,SYN,RST,ACK/SYN ctstate NEW 2410 154K ICMP icmp -- any any anywhere anywhere ctstate NEW 396 63275 REJECT udp -- any any anywhere anywhere reject-with icmp-port-unreachable 2916 179K REJECT all -- any any anywhere anywhere reject-with icmp-proto-unreachable 0 0 ACCEPT tcp -- any any anywhere anywhere tcp dpt:ssh ctstate NEW,ESTABLISHED Compare this to previous output and you’ll see two new columns: pkts and bytes. Resetting Packet and Byte Counters You can reset these counters using the -Z option. This happens automatically on reboot, but can also be done manually to test for new traffic: sudo iptables -Z To reset a specific chain: sudo iptables -Z OUTPUT To reset a specific rule in a chain by number: sudo iptables -Z OUTPUT 2 Deleting Rules Deleting by Specification Use -D followed by the full rule specification. View existing rules first. For example, to remove the rule that drops invalid outgoing traffic: sudo iptables -D OUTPUT -m conntrack --ctstate INVALID -j DROP No need to use -A when deleting. Deleting by Rule Number Use --line-numbers to get rule numbers: sudo iptables -L --line-numbers Sample output: Chain INPUT (policy DROP) num target prot opt source destination 1 ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED 2 ACCEPT all -- anywhere anywhere 3 DROP all -- anywhere anywhere ctstate INVALID ... Then delete by number: sudo iptables -D INPUT 3 Flushing Chains Be cautious when flushing chains; you could block your SSH connection. Flush a Single Chain sudo iptables -F INPUT Flush All Chains sudo iptables -F This command allows all traffic (inbound, outbound, forwarded), essentially disabling the firewall. If you run it on a production system, you’ll need to reconfigure the firewall from scratch. Always back up your current rules: iptables-save > iptables_backup.txt Restore them later with: iptables-restore < iptables_backup.txt Before flushing, set the default policy to ACCEPT to avoid losing SSH access: sudo iptables -P INPUT ACCEPT sudo iptables -P FORWARD ACCEPT sudo iptables -P OUTPUT ACCEPT Then flush everything: sudo iptables -t nat -F sudo iptables -t mangle -F sudo iptables -F sudo iptables -X This allows all traffic. If you list rules after this, only the default chains (INPUT, FORWARD, OUTPUT) will be present. Conclusion This tutorial provides practical guidance on how to view, reset, and delete iptables firewall rules and perform similar actions on specific chains. Keep in mind that any changes will be lost upon server reboot unless saved.
23 June 2025 · 6 min to read
Linux

How to Mount an SMB Share in Linux

The Server Message Block (SMB) protocol facilitates network file sharing, allowing applications to read and write to files and request services from server programs. This protocol is pivotal for seamless communication between different devices in a network, particularly in mixed OS environments like Windows and Linux. Mounting an SMB share in Linux enables users to access files on a Windows server or another SMB-enabled device directly from their Linux system. This tutorial will guide you through the process of mounting an SMB share on Linux, ensuring smooth file sharing and network communication. Prerequisites for Mounting SMB Shares Before mounting an SMB share, ensure the following prerequisites are met: A Linux system, such as a Hostman cheap cloud server, with root or sudo privileges. The cifs-utils package installed on your Linux system. Access credentials (username and password) for the SMB share. Network connectivity between your Linux system and the SMB server. Installing Necessary Packages The cifs-utils package is essential for mounting SMB shares on Linux. Additionally, the psmisc package provides the fuser command, which helps manage and monitor file usage. Update Package List and Upgrade System First, update your package list and upgrade your system: sudo apt update Install cifs-utils and psmisc Install the necessary packages: sudo apt install cifs-utils psmisc Verify Installation Verify the installation of cifs-utils and availability of the fuser command: mount -t cifsfuser Finding SMB Share Details Identify the SMB share details, including the server name or IP address and the share name. You might need to consult your network administrator or check the server configuration. Example: Server: smbserver.example.com Share: sharedfolder Mounting SMB Shares Using the mount Command To mount the SMB share, use the mount command with the -t cifs option, specifying the SMB protocol. Create a directory to serve as the mount point: sudo mkdir /mnt/smb_share Mount the SMB share using the following command: sudo mount -t cifs -o username=your_username,password=your_password //192.0.2.17/SharedFiles /mnt/smb_share Replace your_username and your_password with your actual username and password. Ensure /mnt/smb_share is an existing directory. Verifying the Mount To confirm that the SMB share is successfully mounted, use the mount command: mount -t cifs Navigate to the mount point and list the files: cd /mnt/smb_sharels Creating a Credentials File To avoid entering credentials each time, create a credentials file. This file should be hidden and secured. Use a text editor to create the file: nano ~/.smbcredentials Add the following content, replacing with your actual credentials: username=your_usernamepassword=your_password Set appropriate permissions for the file: sudo chown your_username: ~/.smbcredentialssudo chmod 600 ~/.smbcredentials Mount Using the Credentials File Mount the SMB share using the credentials file: sudo mount -t cifs -o credentials=~/.smbcredentials //192.168.2.12/SharedFiles /mnt/smb_share Automating SMB Share Mounts To automate the mounting process, add an entry to the /etc/fstab file. This will ensure the SMB share is mounted at boot. 1. Open /etc/fstab for editing: sudo nano /etc/fstab 2. Add the following line: //smbserver.example.com/sharedfolder /mnt/smbshare cifs username=johndoe,password=securepassword,iocharset=utf8,sec=ntlm 0 0 3. Save and close the file. 4. Test the fstab entry: sudo mount -a Ensure no errors are displayed. Troubleshooting Common Issues Permission Denied Check your credentials and permissions on the SMB server. No Such File or Directory Ensure the server IP, share path, and mount point are correct. Mount Error 13 = Permission Denied Double-check your username and password. Mount Error 112 = Host is Down Verify network connectivity and server availability. Unmounting an SMB Share To unmount the SMB share, use the umount command followed by the mount point: sudo umount /mnt/smb_share Conclusion Mounting an SMB share in Linux is a straightforward process that enhances file sharing capabilities across different operating systems. By following this tutorial, you can efficiently set up and troubleshoot SMB share mounts, facilitating seamless network communication and file access. Don't forget to check how to configure server image on Lunix! Frequently Asked Questions What is Samba in Linux and how does it relate to SMB? Samba is an open-source implementation of the SMB/CIFS protocol in Linux. It allows Linux systems to share files and printers with Windows devices over a network. What is the command to mount a Windows share in Linux? Use mount -t cifs //server/share /mnt/share -o username=your_user. How can I auto-mount an SMB share on boot in Linux? Add the mount configuration to /etc/fstab using proper credentials. Do I need root access to mount an SMB share? For traditional mounting, yes. But user-space tools like gio mount can be used without root.
16 June 2025 · 4 min to read

Do you have questions,
comments, or concerns?

Our professionals are available to assist you at any moment,
whether you need help or are just unsure of where to start.
Email us
Hostman's Support