Linux AWK system Function: Execute Shell Commands

The system function in awk allows you to execute shell commands within awk.

This tutorial will introduce you to the awk system function.

You’ll learn how to execute shell commands within awk, manage input to avoid security vulnerabilities, and dynamically construct commands to handle a wide range of tasks.

 

 

Basic Syntax and Usage

Here’s a basic example:

awk 'BEGIN { system("date") }'

Output:

Sat Mar 30 15:20:49 UTC 2024

This command uses awk to execute the date command in the shell.

The BEGIN block runs before processing any lines of a file.

 

Execute Single and Multiple Commands

Execute a Single Command

Suppose you want to check the disk usage of your system, you can use the df command within awk. Here’s how:

awk 'BEGIN { system("df -h") }'

Output:

Filesystem      Size  Used Avail Use% Mounted on
tmpfs           388M  1.7M  387M   1% /run
/dev/sda1       217G  9.8G  196G   5% /
tmpfs           1.9G     0  1.9G   0% /dev/shm
tmpfs           5.0M  4.0K  5.0M   1% /run/lock
/dev/sda4       266G  3.4M  253G   1% /home
tmpfs           388M  100K  388M   1% /run/user/1000

Execute Multiple Commands

When you need to execute multiple commands, you can chain them using a semicolon (;).

For example, to list the current directory contents and display the current date, you can use:

awk 'BEGIN { system("ls; date") }'

Output:

file1.txt  file2.txt  data.txt
Sat Mar 30 15:45:32 UTC 2024

 

Return Values and Exit Status

When you use the awk system function, it returns the exit status of the command it executes.

This status is a numeric value, typically 0 for success and a non-zero value for failure.

awk 'BEGIN { exit_status = system("ls non_existent_file"); print "Exit Status:", exit_status }'

Output:

ls: cannot access 'non_existent_file': No such file or directory
Exit Status: 2

This output shows that attempting to list a non-existent file results in an error and an exit status of 2 which means a failure.

Handle Multiple Commands

When executing multiple commands, the system function returns the exit status of the last command executed.

awk 'BEGIN { exit_status = system("echo Hello; false"); print "Exit Status:", exit_status }'

Output:

Hello
Exit Status: 1

Even though the first command (echo Hello) succeeds, the exit status reflects the failure of the second command (false, which always returns a non-zero exit status).

Using Exit Statuses in Scripts

You can check the exit status if it was successful or not:

awk '{
    exit_status = system("ping -c 1 example.com");
    if (exit_status == 0) 
        system("echo Ping successful");
    else 
        system("echo Ping failed");
}'

Output:

PING example.com (93.184.216.34) 56(84) bytes of data.
64 bytes from 93.184.216.34: icmp_seq=1 ttl=56 time=11.3 ms

--- example.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 11.311/11.311/11.311/0.000 ms
Ping successful

In this script, awk runs a ping command and then decides which message to print based on the success (exit status 0) or failure of the ping.

 

Dynamically Constructing Shell Commands

Dynamically constructing commands means that the command string is built during the execution of the script, often based on variable content or runtime conditions.

Assume you want to dynamically construct a command to create a directory with a name based on a variable:

awk 'BEGIN {
    dirName = "backup_" strftime("%Y-%m-%d")
    cmd = "mkdir " dirName
    system(cmd)
}'

In this script, awk constructs a command to create a directory. The directory name includes the current date to ensure a unique folder name each time the script runs.

Moving to a more advanced example, suppose you want to dynamically construct a command based on file contents.

For instance, reading from a file and taking actions based on its content:

awk '{
    if ($1 == "CREATE") {
        cmd = "touch " $2
        system(cmd)
    } else if ($1 == "DELETE") {
        cmd = "rm " $2
        system(cmd)
    }
}' commands.txt

Assuming commands.txt contains lines like CREATE file1.txt and DELETE file2.txt, this script will create or delete files accordingly.

This script reads commands from commands.txt and executes them.

 

Avoid Command Injection Vulnerabilities

Command injection is a security vulnerability that allows an attacker to execute arbitrary commands on a host operating system.

These vulnerabilities can occur when untrusted input is used to construct shell commands

The first line of defense against command injection is to validate and sanitize any external input used in your scripts.

Suppose your awk script takes user input to create a directory.

Here’s how you can validate the input:

awk '{
    dirName = $0
    if (dirName ~ /^[a-zA-Z0-9_]+$/) {
        cmd = "mkdir " dirName
        system(cmd)
    } else {
        print "Invalid directory name"
    }
}' <<< "$userInput"

Output:

Invalid directory name

In this script, the regular expression ^[a-zA-Z0-9_]+$ ensures that the directory name contains only letters, numbers, and underscores.

When you try any other input, it will return the error message shown above.

Leave a Reply

Your email address will not be published. Required fields are marked *