How to Create a Bash Script That Only Executes from Cron

Bash scripts are a powerful way to automate tasks on Linux systems. However, in some cases, you may want a script to only execute under…

How to Create a Bash Script That Only Executes from Cron
Photo by Alessandro Venturi on Unsplash

Bash scripts are a powerful way to automate tasks on Linux systems. However, in some cases, you may want a script to only execute under specific circumstances — such as when it’s run by the cron scheduler and not manually. This can be useful for sensitive scripts where manual execution could cause issues or for scripts designed specifically for automated environments.

In this article, we’ll walk through the steps to create a Bash script that only executes when run from cron or when a specific parameter, like --force, is provided manually.

Table of Contents

  1. Understanding the Requirements
  2. Creating the Script
  3. Adding the Script to Cron
  4. Testing the Script
  5. Summary

1. Understanding the Requirements

Our goal is to create a script that:

  • Runs only from cron by default.
  • Allows manual execution only if a specific parameter (e.g., --force) is provided.
  • Rejects manual execution without --force, providing a message that explains the restriction.

We’ll accomplish this by:

  1. Checking for a non-interactive environment, which indicates that the script is being executed by cron.
  2. Adding a parameter check to allow manual execution with a specific flag.

2. Creating the Script

Start by creating a new Bash script file. For this example, let’s call it cron_protected_script.sh. Open the file with a text editor and add the following code:

#!/bin/bash 
 
# Check for the --force parameter 
FORCE=false 
if [ "$1" == "--force" ]; then 
  FORCE=true 
fi 
 
# Function to check if the script is running from cron 
is_running_from_cron() { 
  [ -z "$PS1" ] && [ -z "$(tty)" ] 
} 
 
# Main execution condition 
if $FORCE || is_running_from_cron; then 
  echo "Script is running..." 
 
  # Place your main script code here 
 
else 
  echo "This script can only be run from cron or with the --force parameter." 
  exit 1 
fi

Code Explanation

  • Parameter Check (--force): The script checks if --force is passed as the first argument when executed. If --force is present, it sets the FORCE variable to true.
  • Function to Detect cron: The is_running_from_cron function checks for cron-specific conditions. In a cron job, the $PS1 variable (which defines the shell prompt) is typically absent, and tty (which identifies the terminal) is empty, as there’s no interactive terminal. Thus, the function will return true only if the script is run in a non-interactive environment like cron.
  • Main Execution Condition: The script will run if either the --force parameter is provided or the script is running from cron. Otherwise, it prints a message and exits.

3. Adding the Script to Cron

To schedule the script with cron, follow these steps:

  1. Make the Script Executable: First, save the file and give it executable permissions:
chmod +x /path/to/cron_protected_script.sh

2. Edit the Crontab: Open the cron table (crontab) for editing:

crontab -e

3. Add a Cron Entry: Schedule the script by adding a line to the crontab. For example, to run the script daily at midnight:

0 0 * * * /path/to/cron_protected_script.sh

4. Testing the Script

After setting up the script, it’s essential to test both the cron execution and manual execution scenarios.

  1. Manual Execution without --force: Try running the script without any parameters:
/path/to/cron_protected_script.sh

You should see the following output:

This script can only be run from cron or with the --force parameter.

2. Manual Execution with --force: Now, try running the script with the --force parameter:

/path/to/cron_protected_script.sh --force

This time, the script should execute normally and display the message:

Script is running...

Automated Execution via Cron: Wait for the scheduled time or manually trigger the cron job to verify that the script runs successfully in the cron environment. You can check the system logs (often located in /var/log/syslog on Linux systems) for confirmation that the cron job ran as expected.

5. Summary

In this article, we created a Bash script that only runs when executed by cron or with a specific parameter (--force). This setup provides a layer of protection, ensuring that sensitive or automated scripts are not accidentally triggered in an unintended environment.

Key Points:

  • Parameter Check: Allows manual execution only with --force.
  • Environment Check: Ensures the script runs in a non-interactive environment, typical of cron jobs.
  • Cron Scheduling: Automates script execution using cron, while protecting against accidental manual runs.

This technique is valuable for scripts that should be tightly controlled and run only under specific conditions. By combining parameter checks and environment validation, you can create secure, automated workflows tailored to your needs.

6. Bonus

tty

The `tty` (short for “teletype”) variable in Unix-like systems refers to the terminal associated with a process. When you run the `tty` command in a terminal, it outputs the file path of the terminal device (like `/dev/tty1`), showing that the session has an interactive terminal.

In scripts, checking `tty` is a way to determine if a script has been started in an interactive session or by an automated process like `cron`. Since `cron` jobs run without an attached terminal, `tty` will return an empty result when the script is run by `cron`, making it useful for detecting non-interactive environments.

$PS1

The `$PS1` variable in Unix-like systems defines the primary prompt string in an interactive shell. It controls what you see as the command prompt (e.g., `user@host:~$`).

When `$PS1` is set, it typically indicates that the shell is interactive (like a terminal session). In automated or non-interactive environments, such as scripts run by `cron`, `$PS1` is usually not set. This makes checking `$PS1` useful for distinguishing between interactive and non-interactive environments in scripts.