Score:3

Foreground task scheduling in Linux similar to Windows's Task Scheduler

cn flag

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.

mchid avatar
bo flag
Can you please explain why they don't meet your criteria? Please be specific. Otherwise, we're just going to guess something you've already considered and maybe waste our time. Thanks.
mchid avatar
bo flag
BTW, [to run a cron job at midnight](https://crontab.guru/every-night-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.
mchid avatar
bo flag
Minute is 0. Hour is 0. Every day of the month = * Every month = * Every day of the week = *
Zanna avatar
kr flag
This is pretty broad for our site. It might help if you explain what your script does or share it in the question. Ideally, I'd recommend you have a go at it and identify the issues you run into so that you can ask more specific questions.
Score:8
bo flag

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 avatar
bo flag
However, I think it's probably **not a good idea to run a crontab in the terminal as root. This might result in your Xauthority file losing the correct permissions.** This might not be a problem with Wayland but I'm not sure. That's one of the many reasons it's best to have the output redirected to a file.
Youssif Saeed avatar
cn flag
Thanks for your detailed response. I have tested it and it is working for me. This is exactly what I needed to get started.
TCooper avatar
cn flag
Probably worth mentioning if you want all output to go to your log file, and nowhere else, add "2>&1" where 2 is Standard Error output, and 1 is Standard Output. So send errors to standard output and output all into your log file. Or alternatively, to two different log files: "2>err_log.txt 1>cron_log.txt" - not declaring this defaults to the system email for cron errors, which I find... annoying, at least compared to using a log file
fr flag
A.L
`0 0 * * echo "hello world" > /home/youssif/helloworld.log` will erase the log every day. With `>>` it will add the content to the end of the file, every day.
mchid avatar
bo flag
@A.L Yeah I decided to go with that because it would be more like opening a terminal and providing the output for a single session. I think it would be better to add a date to prefix the logs and that just seemed like it would complicate an already complicated answer.
Score:4
cn flag

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.

Score:0
es flag

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.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.