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.
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:
cut -d '"' -f2 access.log: This splits each line at the quotation marks and selects the second field, which contains the HTTP request.|: This pipes the output of thecutcommand to theheadcommand.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:
grep "/admin" access.log: Searches for lines containing "/admin" in the access.log file.|: Pipes the output of grep to the head command.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:
- It's fast:
headonly reads the beginning of the file, so it completes quickly even for enormous files. - It's memory-efficient:
headdoesn't need to load the entire file into memory. - 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:
- Use
headto view the first 10 lines of a file by default. - Customize the number of lines displayed using the
-noption. - Examine multiple files simultaneously with
head. - Combine
headwith other commands likecutandgrepusing pipes. - Use
headto 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.



