4

I have a batch application on Windows that I run every day at midnight. Recently, I converted this into a Linux shell script on a Linux machine and would like to similarly run it every day at midnight. My requirements are as follows:-

  • For the shell script to run in the foreground - this is to allow me to see the output of the running process and correct/fix things if it fails.
  • Similar to how the Windows task scheduler works, I would like to have a list of scripts that I can run, and those lists can be enabled/disabled.
  • (Optional) Ideally, the Task Scheduler equivalent can be modified programmatically. This would allow me to disable/enable tasks based on the result of an already run task.

Is this doable? I've seen the links below but they don't contain all the criteria that I need for my use case. If one of the links below is the correct way to go then an example can be really helpful.

3 Answers3

10

To run a cron job at midnight, you would prefix your command or the path to your script with:

0 0 * * *

For example, to run /home/youssif/myscript , you would use:

0 0 * * /home/youssif/myscript

in your crontab file.


To edit your crontab file, use crontab -e to run the command as your current user. Alternatively, if you absolutely need to run the command as root, you can run sudo crontab -e to edit your crontab file.


To run the command in a terminal (not a good idea if you run the command as root), you will need to specify the display to use in your command or in your script. To do this, assuming your $DISPLAY is :0 (default) you can prefix your command with the following variable:

DISPLAY=:0

Also, a terminal will typically close after the command is executed but you can use the hold option with xterm to keep the terminal open.

So, to run echo "hello world" in a terminal at midnight, your command would look like this:

0 0 * * DISPLAY=:0 xterm -hold -e 'echo "hello world"'

or to run your script:

0 0 * * DISPLAY=:0 xterm -hold -e '/home/youssif/myscript'

However, the standard way to inspect the output of a cronjob is to redirect the terminal output to a file which you can look at later.

For example, to redirect the terminal output to the file /home/youssif/helloworld.log you would use the following line in your crontab file:

0 0 * * echo "hello world" > /home/youssif/helloworld.log

Alternatively, you can also use the tee command to redirect the output like this:

0 0 * * echo "hello world" | tee /home/youssif/helloworld.log

Finally, you can use the cat command to view the contents of the file:

cat /home/youssif/helloworld.log

This way, the command can run in the background but you can still inspect the output.


To disable/enable tasks based on the result of an already run task, I think this would really be more appropriate for a separate question. I believe your answer would involve using an "if then else" statement in a bash script.


EDIT:

As @Tcooper pointed out, we have to add 2>&1 to redirect all the output, including error messages so you might want to use something like this instead:

0 0 * * echo "hello world" 2>&1 > /home/youssif/helloworld.log

or

0 0 * * echo "hello world" 2>&1 | tee /home/youssif/helloworld.log
mchid
  • 44,904
  • 8
  • 102
  • 162
5

All of these requirements can be met easily. The traditional way to schedule jobs in linux is crontab. The "modern" way to schedule jobs in linux is systemd. crontab continues to be supported on Ubuntu.

Your Requirement 1: is unusual: are you waiting at your computer at midnight when the task starts? Otherwise, that is why log files are used in linux. The system administrator can then inspect the logs during day time to check how things proceeded.

If needed, jobs can be launched in a graphical terminal emulator. That, however, requires you to be logged in anytime, which may be less ideal from a security point of view.

crontab and/or systemd satisfy requirement 2. You see your list of jobs in the output of systemd list-units or in the crontab file. You can enable/disable/remove by systemd commands or by removing/adding a comment # sign in front of the task, or deleting the line altogether.

Requirement 3 can be easily scripted. A subsequent job can read what a previous job has done, and act accordingly.

vanadium
  • 97,564
0

I must emphasize that some of what you're asking is pretty unconventional, and for good reason. For example, running a scheduled task in the foreground means that the output will be lost once it exceeds the scrollback buffer (i.e. the capacity to store "output history") of your terminal. That's why it's much more conventional to send output to a log file instead of displaying it directly in the terminal, and I definitely recommend that you stick with the convention here.

That being said... supercronic is a task scheduler that you can run as a regular (non-root) user, in the foreground, that has the capacity to log output directly to the terminal. It reads a crontab-like file in which you can specify a list of scripts to run and the times at which to run them, and you can arrange for some automated process to edit the file and signal the supercronic process so it picks up the changes. So it seems to meet all your requirements.

David Z
  • 10,945