How to Schedule Cron jobs tasks in Unix/Linux

Learn to schedule tasks using cronjob in Unix. This guide explains how to manage cronjob tasks in unix with practical examples.

Cron jobs are essential tools in Unix/Linux systems for automating repetitive tasks. Whether you’re backing up files, syncing data, or running maintenance scripts, cron jobs make sure your tasks run consistently and on time without manual intervention.

In this article, we’ll walk through how to add jobs to the cron scheduler (crontab) and understand its syntax so you can schedule tasks efficiently.

What is a Cron Job in Unix?

A cron job is a scheduled command or script that runs automatically at specified intervals. The cron daemon (crond) handles these jobs in the background on Unix-like operating systems.

Viewing and Editing Crontabation files

Each user has their own crontab file. To view or edit your crontab:

crontab -e

This command opens your crontab in the default system editor (like vi or nano), allowing you to add or modify jobs.

To view your current scheduled jobs:

crontab -l

To remove all scheduled cron jobs:

crontab -r

Unix Cron jobs Syntax Breakdown

A typical cron job line looks like this:

* * * * * command to be executed
- - - - -
| | | | |
| | | | ----- Day of week (0 - 7) (Sunday=0 or 7)
| | | ------- Month (1 - 12)
| | --------- Day of month (1 - 31)
| ----------- Hour (0 - 23)
------------- Minute (0 - 59)

Each * represents a time or date field. And each field can be configured based on the following table.

FieldValue RangeDescription
Minute0–59Minute of the hour
Hour0–23Hour of the day
Day1–31Day of the month
Month1–12Month of the year
Weekday0–7 (0 or 7 = Sunday)Day of the week

Example: Run backup cron job script

If you wished to have a script named /root/backup.sh run every day at 3 am, your crontab entry would look like as follows. First, install your cronjob by running the following command:

# crontab -e

Append the following entry:

0 3 * * * /root/backup.sh

Save and close the file.

More examples

To run /path/to/command five minutes after midnight, every day, enter:

5 0 * * * /path/to/command

Run /path/to/script.sh at 2:15 pm on the first of every month, enter:

15 14 1 * * /path/to/script.sh

To run any PHP script /scripts/phpscript.php at 10 pm on weekdays, enter:

0 22 * * 1-5 /scripts/phpscript.php

Run /root/scripts/perl/perlscript.pl at 23 minutes after midnight, 2am, 4am …, everyday, enter:

23 0-23/2 * * * /root/scripts/perl/perlscript.pl

Run /path/to/unixcommand at 5 after 4 every Sunday, enter:

5 4 * * sun /path/to/unixcommand

You can schedule any command using the cron jobs. For running any script using cron job, make sure your script has executable permissions.

If your script uses environment variables or specific paths, be sure to define them inside the script or call the appropriate environment setup.

Redirecting Output

To log output or errors, you can use the following command and save the logs in file:

0 0 * * * /path/to/script.sh >> /var/log/myscript.log 2>&1
  • >> appends standard output to a log file
  • 2>&1 redirects errors (stderr) to the same log file without displaying it to the console.

System-Wide Cron Jobs

System-wide cron files can be added to:

  • Hourly, daily, weekly, monthly: /etc/cron.hourly/, /etc/cron.daily/, etc.
  • /etc/crontab
  • /etc/cron.d/

Conclusion

Cron jobs are powerful for scheduling recurring tasks in Unix/Linux environments. By mastering crontab syntax and scheduling structure, you can automate system maintenance, backups, and custom scripts with ease.

Make sure to test your scripts before scheduling them and check logs regularly to confirm successful execution.

See also

See man pages for more information cron(8), crontab(1), crontab(5), run-parts(8)

Automatically Kill Slow MySQL Queries After N Seconds

Learn how to detect and automatically terminate slow MySQL queries after a set duration. Improve performance and avoid database slowdowns.

Maintaining a performant MySQL-backed application requires smart tuning. Without it, connections may pile up, queries stall, and user experience suffers dramatically, especially due to slow queries.

If you’re using persistent connections, idle or long-running queries can accumulate in SLEEP mode for a log time. One quick solution – especially on MySQL ≥ 5.1 – is to periodically scan the process list and terminate any query that’s been running longer than your acceptable threshold and currently in SLEEP mode.

In this post, we will learn some techniques to identify these slow queries and kill them to improve the performance of the application.

Step 1: Generate KILL QUERY Statements

This SQL query will produce the necessary KILL QUERY commands for any non-system query exceeding your time limit (e.g., 1200 seconds = 20 minutes):

SELECT
  GROUP_CONCAT(
    CONCAT('KILL QUERY ', id, ';')
    SEPARATOR ' '
  ) AS kill_cmds
FROM information_schema.processlist
WHERE user <> 'system user'
  AND time >= 1200;

You can customize the filter via the info column – for instance, if you want queries from specific database (db) or certain query patterns, you can apply those filters to info column and update the above query accordingly.

This query gives you the complete list of slow queries as per your filters. But, you need to run it everytime, whenever you want this data.

So, to automate this process, add this query to cronjob via a shell script.

Step 2: Automate with a Shell Script

Wrap this logic in a shell script and schedule it with cron to run at regular intervals. Here’s a refined example:

SECONDS_TOO_LONG=1200

QUERIES_RUNNING_TOO_LONG=`mysql -uroot -ppassword -ANe"SELECT COUNT(1) FROM information_schema.processlist WHERE user <> 'system user' AND time >= ${SECONDS_TOO_LONG}"`

if [ ${QUERIES_RUNNING_TOO_LONG} -gt 0 ]
then
    KILLPROC_SQLSTMT="SELECT GROUP_CONCAT(CONCAT('KILL QUERY ',id,';') SEPARATOR ' ') KillQuery FROM information_schema.processlist WHERE user <> 'system user' AND time >= ${SECONDS_TOO_LONG}"
    mysql -uroot -ppassword -ANe"${KILLPROC_SQLSTMT}" | mysql -uroot -ppassword
fi

This ends all slow MySQL queries running over 20 minutes and can be scheduled every few minutes in crontab.

Alternative: Log and Kill via a Temporary SQL File

Alternatively, if you want to log all the slow MySQL queries before killing them, here’s a safe method:

SECONDS_TOO_LONG=1200

QUERIES_RUNNING_TOO_LONG=`mysql -uroot -ppassword -ANe"SELECT COUNT(1) FROM information_schema.processlist WHERE user <> 'system user' AND time >= ${SECONDS_TOO_LONG}"`
if [ ${QUERIES_RUNNING_TOO_LONG} -gt 0 ]
then
    KILLPROC_SQLSTMT="SELECT CONCAT('KILL QUERY ',id,';') KillQuery FROM information_schema.processlist WHERE user <> 'system user' AND time >= ${SECONDS_TOO_LONG}"
    mysql -uroot -ppassword -ANe"${KILLPROC_SQLSTMT}" > /tmp/kill_log_queries.sql
    mysql -uroot -ppassword < /tmp/kill_log_queries.sql
fi

This approach gives you a chance to log or inspect the kill commands before they run.

Want to learn more about tuning MySQL performance? Get High Performance MySQL book from https://amzn.to/4dVaueF

Built-In Per-Session Execution Timeout (MySQL 5.7+)

If you’re using MySQL 5.7.4+, a cleaner solution exists:

SET GLOBAL max_execution_time = 5000; -- Timeout in milliseconds

This applies a soft execution limit to all SELECT queries (read-only) at runtime. Once exceeded, MySQL aborts the query with an error but keeps the session alive.

You can also set per-session limits:

SET SESSION max_execution_time = 2000;

Or use the hint syntax on specific queries:

SELECT /*+ MAX_EXECUTION_TIME(1000) */ * FROM your_table; 

Conclusion

Choose the approach that fits your environment:

  • Older MySQL (< 5.7): Use a cron-driven shell script targeting INFORMATION_SCHEMA.PROCESSLIST.
  • MySQL 5.7.4 and above: Prefer max_execution_time or per-query hints for cleaner, built-in enforcement.

They all help safeguard against runaway queries that could otherwise lock up your server.

Disclaimer: This post contains affiliate links. If you use these links to buy something, I may earn a commission at no extra cost to you.

How to Execute a JAR File from the Terminal on Ubuntu?

Learn how to run JAR files directly from the terminal on ubuntu. Includes syntax examples, troubleshooting tips, and Java runtime requirements.

To execute .jar file, java command should be used as below:

java -jar {path_of_the_file}/{file_name}.jar

And to execute above command, Java package must be installed on Ubuntu PC. To check if java package is already installed, execute below command in a terminal:

java -version 

It should display current version of Java package installed.

If it displays “The program java can be found in the following packages”, It means Java hasn’t been installed yet. Execute below command in a terminal to install java package,

sudo apt-get install default-jre

This will install the Java Runtime Environment (JRE) only not Java Development Kit (JDK). If Java Development Kit (JDK) is needed, which is usually needed to compile Java applications, execute the following command in terminal:

sudo apt-get install default-jdk

That is everything to install Java. Now run first command to execute .jar file.

How to Reset a Forgotten phpMyAdmin Password

Forgot your phpMyAdmin password? Follow this simple guide to reset your MySQL root or user password and regain access to phpMyAdmin on localhost or server.

Forgetting your phpMyAdmin password can be frustrating, especially when you’re in the middle of working on a critical project. Fortunately, resetting the password is a straightforward process. This guide walks you through the steps needed to reset your phpMyAdmin (MySQL/MariaDB) root password on a local or remote server.

Step-by-Step Guide to Reset phpMyAdmin Root Password

Step 1: Stop the MySQL Service

Before making any changes, stop the MySQL or MariaDB service.

sudo systemctl stop mysql

Step 2: Start MySQL in Safe Mode

Run MySQL in safe mode without password authentication.

sudo mysqld_safe --skip-grant-tables &

This allows you to log in without needing a password.

Step 3: Log in to MySQL

Now log into MySQL as the root user:

mysql -u root

You’ll be taken directly to the MySQL shell.

Step 4: Change the Root Password

Run the following commands to change the root password.

For MySQL 5.7+ or MariaDB 10.1+:

FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost' IDENTIFIED BY 'your_new_password';

For older versions:

USE mysql;
UPDATE user SET password=PASSWORD('your_new_password') WHERE User='root';
FLUSH PRIVILEGES;

Replace 'your_new_password' with your desired password.

Step 5: Stop MySQL Safe Mode and Restart Normally

Press Ctrl+C to stop the MySQL safe mode process (if it’s running in foreground), or kill it using:

sudo killall -9 mysqld_safe
sudo killall -9 mysqld

Then start the service again:

sudo systemctl start mysql

Step 6: Test Login to phpMyAdmin

Go to http://localhost/phpmyadmin or your server’s phpMyAdmin URL and log in using:

  • Username: root
  • Password: the new password you just set

If successful, you’re good to go!

Tips for Better Security

  • Avoid using the root account for daily tasks. Create a separate user with limited privileges.
  • Use strong, unique passwords and store them securely using a password manager.
  • Regularly update MySQL/MariaDB and phpMyAdmin for security patches.

Common Issues & Fixes

Issue: Access denied for user 'root'@'localhost'
Fix: Ensure you flushed privileges and restarted the MySQL server after changing the password.

Issue: phpMyAdmin login loop
Fix: Check config.inc.php in your phpMyAdmin directory. Ensure $cfg['Servers'][$i]['auth_type'] is set to 'cookie'.

Conclusion

Resetting a forgotten phpMyAdmin password isn’t difficult when you follow the correct steps. Always remember to restart the MySQL service after resetting the password and ensure your configuration files are properly set. Keeping your credentials secure and using non-root accounts for regular usage can further enhance your database security.

Fix “Can’t Upgrade Due to Low Disk Space on /boot” in Linux

Learn how to resolve the ‘low disk space on /boot’ error during Linux upgrades. Follow step-by-step solutions to free up /boot and complete your system updates.

Your /boot partition is filled with old kernels. It does that sometimes, not sure why it is never fixed. You can easily remove the old kernels if you know which packages they came in.

First check uname -a to check your current version.

Then run the following command:

dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d'

This command will list all packages that you no longer need. I don’t like removing them automatically, I like to be in control when it comes to removing kernels. So for every package listed do the following:

sudo apt-get -y purge some-kernel-package

Intermezzo

This intermezzo describes in more detail how the commands work and tries to fix an issue with linux-libc-dev:amd64. Most users can skip this paragraph.

  • dpkg -l 'linux-*' list all packages that have a name starting with ‘linux-‘
  • sed '/^ii/!d; remove all lines that do *not* start withii`
  • uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/" find the current running kernel version
  • /'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d Remove all lines, except the ones containing the current running kernel version number
  • s/^[^ ]* [^ ]* \([^ ]*\).*/\1/ For each line list only the package name
  • /[0-9]/!d Remove lines that do not contain numbers.

To fix Frederick Nord’s issue I think the command can be amended as follows:

dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d;/^linux-\(headers\|image\)/!d'

It basically adds an extra filter:

  • /^linux-(headers\|image)/!d Delete all lines that do not start with linux-headers or linux-image

/Intermezzo

Where some-kernel-package can be replaced with one of the packages listed. Just beware that you don’t remove the kernel packages that are in current use (as listed by the uname -a) eg. sudo apt-get purge -y linux-headers-3.0.0-12 etc.

It can be automated further using the xargs command, but I don’t like that. It is a personal thing. However, here’s the command to do so:

dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d' | xargs sudo apt-get -y purge

This is what my /boot looks like, one spare kernel (2.6.38-11) just in case and 3.2.0-24 being current:

$ ls -l /boot
total 59388
-rw-r--r-- 1 root root   730545 Sep 13  2011 abi-2.6.38-11-generic
-rw-r--r-- 1 root root   791023 Apr 25 13:51 abi-3.2.0-24-generic
-rw-r--r-- 1 root root   130326 Sep 13  2011 config-2.6.38-11-generic
-rw-r--r-- 1 root root   140341 Apr 25 13:51 config-3.2.0-24-generic
drwxr-xr-x 3 root root     5120 May 27 17:46 grub
-rw-r--r-- 1 root root 20883146 Oct  1  2011 initrd.img-2.6.38-11-generic
-rw-r--r-- 1 root root 22474219 May  5 09:04 initrd.img-3.2.0-24-generic
drwxr-xr-x 2 root root    12288 Apr 16  2009 lost+found
-rw-r--r-- 1 root root   176764 Nov 27 11:00 memtest86+.bin
-rw-r--r-- 1 root root   178944 Nov 27 11:00 memtest86+_multiboot.bin
-rw------- 1 root root  2656297 Sep 13  2011 System.map-2.6.38-11-generic
-rw------- 1 root root  2884358 Apr 25 13:51 System.map-3.2.0-24-generic
-rw------- 1 root root     1369 Sep 13  2011 vmcoreinfo-2.6.38-11-generic
-rw------- 1 root root  4526784 Sep 13  2011 vmlinuz-2.6.38-11-generic
-rw------- 1 root root  4965776 Apr 25 13:51 vmlinuz-3.2.0-24-generic

And file system usage:

$ df -h /boot
Filesystem Size Used Avail Use% Mounted
/dev/sda5  228M  63M  154M  29% /boot