Linux head Command: File Beginning Display

LinuxLinuxBeginner
Practice Now

Introduction

In this lab, we will explore the head command in Linux, a powerful utility for previewing the beginning of text files. Imagine you're a digital detective tasked with quickly scanning through numerous files to find crucial information. The head command will be your trusty magnifying glass, allowing you to peek at the start of files without opening them entirely.

We'll simulate a scenario where you're investigating a collection of log files from a busy web server. Your goal is to efficiently examine these logs to identify potential issues and gather insights. Through this practical exercise, you'll learn how to use the head command effectively, making your file exploration tasks faster and more efficient.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL linux(("`Linux`")) -.-> linux/BasicFileOperationsGroup(["`Basic File Operations`"]) linux(("`Linux`")) -.-> linux/TextProcessingGroup(["`Text Processing`"]) linux/BasicFileOperationsGroup -.-> linux/head("`File Beginning Display`") linux/TextProcessingGroup -.-> linux/grep("`Pattern Searching`") linux/BasicFileOperationsGroup -.-> linux/ls("`Content Listing`") subgraph Lab Skills linux/head -.-> lab-214302{{"`Linux head Command: File Beginning Display`"}} linux/grep -.-> lab-214302{{"`Linux head Command: File Beginning Display`"}} linux/ls -.-> lab-214302{{"`Linux head Command: File Beginning Display`"}} end

Understanding the Basics of head

Let's start by examining a simple log file to understand how head works.

First, navigate to the project directory:

cd /home/labex/project

Now, let's use the head command on a file named access.log:

head access.log

You should see output similar to this:

192.168.1.100 - - [01/Jan/2024:00:00:01 +0000] "GET /index.html HTTP/1.1" 200 1234
192.168.1.101 - - [01/Jan/2024:00:00:02 +0000] "GET /style.css HTTP/1.1" 200 567
192.168.1.102 - - [01/Jan/2024:00:00:03 +0000] "GET /logo.png HTTP/1.1" 200 2345
192.168.1.103 - - [01/Jan/2024:00:00:04 +0000] "POST /login HTTP/1.1" 302 -
192.168.1.104 - - [01/Jan/2024:00:00:05 +0000] "GET /dashboard HTTP/1.1" 200 3456
192.168.1.105 - - [01/Jan/2024:00:00:06 +0000] "GET /api/user HTTP/1.1" 200 789
192.168.1.106 - - [01/Jan/2024:00:00:07 +0000] "GET /images/banner.jpg HTTP/1.1" 200 4567
192.168.1.107 - - [01/Jan/2024:00:00:08 +0000] "POST /comment HTTP/1.1" 201 -
192.168.1.108 - - [01/Jan/2024:00:00:09 +0000] "GET /search?q=linux HTTP/1.1" 200 2345
192.168.1.109 - - [01/Jan/2024:00:00:10 +0000] "GET /about HTTP/1.1" 200 1234

By default, head displays the first 10 lines of the file. Each line in this log represents a single request to the web server, showing the IP address, timestamp, HTTP method, requested resource, status code, and response size.

Customizing the Number of Lines

Sometimes, 10 lines might be too many or too few. Let's learn how to customize the number of lines head displays.

To view only the first 5 lines of the log, use the -n option:

head -n 5 access.log

This command should output:

192.168.1.100 - - [01/Jan/2024:00:00:01 +0000] "GET /index.html HTTP/1.1" 200 1234
192.168.1.101 - - [01/Jan/2024:00:00:02 +0000] "GET /style.css HTTP/1.1" 200 567
192.168.1.102 - - [01/Jan/2024:00:00:03 +0000] "GET /logo.png HTTP/1.1" 200 2345
192.168.1.103 - - [01/Jan/2024:00:00:04 +0000] "POST /login HTTP/1.1" 302 -
192.168.1.104 - - [01/Jan/2024:00:00:05 +0000] "GET /dashboard HTTP/1.1" 200 3456

This can be particularly useful when you're looking for specific information near the beginning of a file but don't need to see all 10 lines.

Examining Multiple Files

As a file detective, you often need to look at multiple files quickly. The head command allows you to view the beginnings of multiple files at once.

Let's examine the starts of both access.log and error.log:

head access.log error.log

You should see output similar to this:

==> access.log <==
192.168.1.120 - - [01/Jan/2024:00:00:53 +0000] "POST /about HTTP/1.1" 200 7616
192.168.1.147 - - [01/Jan/2024:00:00:45 +0000] "GET /dashboard HTTP/1.1" 200 7348
192.168.1.138 - - [01/Jan/2024:00:00:03 +0000] "DELETE /comment HTTP/1.1" 400 8341
192.168.1.138 - - [01/Jan/2024:00:00:31 +0000] "DELETE /about HTTP/1.1" 200 3254
192.168.1.122 - - [01/Jan/2024:00:00:15 +0000] "PUT /index.html HTTP/1.1" 500 6061
192.168.1.125 - - [01/Jan/2024:00:00:09 +0000] "DELETE /logo.png HTTP/1.1" 301 4916
192.168.1.148 - - [01/Jan/2024:00:00:33 +0000] "POST /admin/dashboard HTTP/1.1" 201 5546
192.168.1.146 - - [01/Jan/2024:00:00:56 +0000] "GET /images/banner.jpg HTTP/1.1" 301 2332
192.168.1.195 - - [01/Jan/2024:00:00:12 +0000] "DELETE /dashboard HTTP/1.1" 404 6740
192.168.1.136 - - [01/Jan/2024:00:00:18 +0000] "GET /login HTTP/1.1" 200 2374

==> error.log <==
[01/Jan/2024:00:01:23 +0000] [error] [client 192.168.1.150] File does not exist: /var/www/html/missing.html
[01/Jan/2024:00:02:34 +0000] [error] [client 192.168.1.151] PHP Parse error:  syntax error, unexpected ';' in /var/www/html/index.php on line 30
[01/Jan/2024:00:03:45 +0000] [warn] [client 192.168.1.152] ModSecurity: Access denied with code 403 (phase 2). Matched phrase "sql injection attempt" at REQUEST_URI. [file "/etc/modsecurity/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf"] [line "50"] [id "942100"] [rev ""] [msg "SQL Injection Attack Detected via libinjection"] [data "Matched Data: SQL injection found within REQUEST_URI: /vulnerable.php?id=1'"] [severity "CRITICAL"] [ver "OWASP_CRS/3.3.0"] [maturity "0"] [accuracy "0"] [hostname "example.com"] [uri "/vulnerable.php"] [unique_id "YvKp2H8AAQEAAAxxBGIAAAAC"]
[01/Jan/2024:00:04:56 +0000] [error] [client 192.168.1.153] AH01071: Got error 'PHP message: PHP Fatal error:  Uncaught Error: Call to undefined function mysql_connect() in /var/www/html/db.php:15...'
[01/Jan/2024:00:05:67 +0000] [warn] [client 192.168.1.154] ModSecurity: Warning. Matched "Operator `Ge' with parameter `5' against variable `TX:ANOMALY_SCORE' (Value: `5' ) [file "/etc/modsecurity/rules/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "57"] [id "949110"] [rev ""] [msg "Inbound Anomaly Score Exceeded (Total Score: 5)"] [data ""] [severity "CRITICAL"] [ver "OWASP_CRS/3.3.0"] [maturity "0"] [accuracy "0"] [hostname "example.com"] [uri "/admin"] [unique_id "YvKp2H8AAQEAAAxxBGIAAAAD"]
[01/Jan/2024:00:06:78 +0000] [error] [client 192.168.1.155] PCE: Can't open perl script "/var/www/html/cgi-bin/printenv": No such file or directory
[01/Jan/2024:00:07:89 +0000] [warn] [client 192.168.1.156] ModSecurity: Access denied with code 403 (phase 2). Matched phrase "directory traversal attempt" at ARGS:file. [file "/etc/modsecurity/rules/REQUEST-930-APPLICATION-ATTACK-LFI.conf"] [line "75"] [id "930110"] [rev ""] [msg "Path Traversal Attack (/../)"] [data "Matched Data: ../ found within ARGS:file: ../../../etc/passwd"] [severity "CRITICAL"] [ver "OWASP_CRS/3.3.0"] [maturity "0"] [accuracy "0"] [hostname "example.com"] [uri "/download.php"] [unique_id "YvKp2H8AAQEAAAxxBGIAAAAE"]
[01/Jan/2024:00:08:90 +0000] [error] [client 192.168.1.157] PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes) in /var/www/html/memory_hog.php on line 10
[01/Jan/2024:00:09:01 +0000] [warn] [client 192.168.1.158] ModSecurity: Warning. Pattern match "(?i:(?:[\s'\"`_''\(\)]*?(?:[\d\w]+[\s'\"`_''\(\)]*?){2,}[\s'\"`_''\(\)]*?(?:having|rongjitest|select|union|where|get_lst))" at ARGS:username. [file "/etc/modsecurity/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf"] [line "1126"] [id "942480"] [rev ""] [msg "SQL Injection Attack"] [data "Matched Data: union select found within ARGS:username: admin' UNION SELECT password FROM users--"] [severity "CRITICAL"] [ver "OWASP_CRS/3.3.0"] [maturity "0"] [accuracy "0"] [hostname "example.com"] [uri "/login.php"] [unique_id "YvKp2H8AAQEAAAxxBGIAAAAF"]
[01/Jan/2024:00:10:12 +0000] [error] [client 192.168.1.159] AH01797: client denied by server configuration: /var/www/html/restricted/

Notice how head clearly separates the output from each file with headers. This is incredibly useful when you need to quickly compare the beginnings of multiple files.

Using head with Pipes

As a skilled file detective, you often need to combine commands to filter and analyze data more effectively. The head command works well with pipes, allowing you to chain it with other commands.

Let's say you want to see the first 3 lines of access.log, but only the parts showing the timestamp and the requested resource. You can use the cut command along with head to achieve this:

cut -d '"' -f2 access.log | head -n 3

This command should output:

POST /about HTTP/1.1
GET /dashboard HTTP/1.1
DELETE /comment HTTP/1.1

Here's what this command does:

  1. cut -d '"' -f2 access.log: This splits each line at the quotation marks and selects the second field, which contains the HTTP request.
  2. |: This pipes the output of the cut command to the head command.
  3. head -n 3: This displays only the first 3 lines of the piped input.

This combination allows you to quickly focus on specific parts of the log entries, making your investigation more efficient.

Investigating with head and grep

Now, let's combine head with another powerful command, grep, to search for specific patterns in our logs.

Suppose you've received reports of unusual activity related to the /admin page. You want to check the first few occurrences of /admin in the access log:

grep "/admin" access.log | head -n 3

This command should output something like:

192.168.1.148 - - [01/Jan/2024:00:00:33 +0000] "POST /admin/dashboard HTTP/1.1" 201 5546
192.168.1.115 - - [01/Jan/2024:00:00:22 +0000] "PUT /admin HTTP/1.1" 302 1113
192.168.1.163 - - [01/Jan/2024:00:00:56 +0000] "POST /admin/dashboard HTTP/1.1" 301 815

This command does the following:

  1. grep "/admin" access.log: Searches for lines containing "/admin" in the access.log file.
  2. |: Pipes the output of grep to the head command.
  3. head -n 3: Displays only the first 3 lines of the piped input.

This combination allows you to quickly focus on relevant entries in your log file, making your investigation more targeted and efficient.

Exploring Large Files with head

As a file detective, you often encounter very large log files. The head command is particularly useful for quickly examining the beginning of these files without loading the entire content into memory.

Let's simulate working with a large file by using the access.log file we've been working with. We'll pretend it's much larger than it actually is.

First, let's check the file size:

ls -lh access.log

Now, let's use head to view the first 15 lines:

head -n 15 access.log

You should see output similar to what we've seen before, but with 15 lines instead of 10.

The head command is especially valuable when dealing with very large files because:

  1. It's fast: head only reads the beginning of the file, so it completes quickly even for enormous files.
  2. It's memory-efficient: head doesn't need to load the entire file into memory.
  3. It gives you a quick preview: You can get an idea of the file's structure and content without opening the whole file.

Summary

In this lab, we explored the head command, a powerful tool for quickly examining the beginning of files. We learned how to:

  1. Use head to view the first 10 lines of a file by default.
  2. Customize the number of lines displayed using the -n option.
  3. Examine multiple files simultaneously with head.
  4. Combine head with other commands like cut and grep using pipes.
  5. Use head to efficiently work with large files.

Additional head parameters not covered in this lab:

  • -c: Display the first few bytes of a file instead of lines.
  • -q: Suppress headers when examining multiple files.
  • -v: Always display headers when examining multiple files.

Resources

Other Linux Tutorials you may like