4

I have a crontab that runs like this:

0 0 * * * /execute/shell/script.sh
0 0 * * * /execute/shell/script1.sh
0 0 * * * /execute/shell/script2.sh

And, I want to launch each script in a different screen. But I want to keep that screen running so that anytime I want to see the progress of one of these scripts, I can always just do screen -d -r <PID> and it will reattach the screen for me to ssee the progress.

I'm sure there must be a way to do this. but the similar questions i've found have not answered it.

Crontab start a screen How do I use crontab to start a screen session?

makansij
  • 265

3 Answers3

3

Do you actually have to interact with the commands, or do you just want to see the status before the commands complete, and the results are mailed back to you?

I've encountered a similar "issue", where I was running traceroute(8) and mtr from within cron, to monitor connectivity, with mtr running in a for-loop to provide more precise measurements over a given interval (between 5 and 16.67 minutes (300 to 1000 cycles)), but the whole script designed to run for about an hour (to ensure I don't get spammed with emails), so, I wanted to be able to see the status as it happened.

https://unix.stackexchange.com/questions/61820/how-can-i-access-a-deleted-open-file-on-linux-output-of-a-running-crontab-task

The way cron works is it creates a temporary file in /tmp, and immediately calls unlink(2) (but still keeping the file open); this is subsequently used to store the output of your scripts before they finish, and it gets emailed to you.

As such, you can use lsof -n -c cron (and/or lsof -n | fgrep cron) to find out the number of open files that have been deleted, and then access those files via the /proc/$PID/fd/$FD namespace to see the output of your scripts running from within cron, without any need for screen.

cnst
  • 14,646
2

You may try something like this:

cat /etc/cron.d/test
*/10 * * * * root screen -dmS script bash -c '/execute/shell/script.sh; exec bash'
*/10 * * * * root screen -dmS script1 bash -c '/execute/shell/script1.sh; exec bash'
*/10 * * * * root screen -dmS script2 bash -c '/execute/shell/script2.sh; exec bash'

It should work I believe. Sure, edit times to whatever you need.

2

The above (Jaroslav Kucera answer) will not work as intended because on the second invocation the commands will spawn new screen sessions with same names as the previous ones.

If you want to have always the same screen sessions for the same scripts then I would do it a bit more trickier.

I would run those sessions at @reboot cron with scripts that make a constant loop like

#!/bin/bash
while true; do
if [ -f /tmp/script1_enabled ]; then
    script1_function_or_command
    rm /tmp/script1_enabled
fi

sleep 60;
done 

Which would run each minute checking for the presence of named file in /tmp - if it exists then run the command, otherwise wait another minute.

The second part would be cron commands that create those files each day - working like a boolean flag to initiate the script invocation.

After the script is done the file would be removed. That way you can keep same sessions for your scripts, and still run it in intervals of your liking.

If the 60 second delay in the loop is too much for you (there is no way to precisely run the script at given time with this method as the sleep will be executed in unpredictable time), then you can set up inotifywait watches and execute scripts as soon as the file is created.

the cron would look like :

@reboot screen -dmS script1 /usr/local/bin/script1_watcher
@reboot screen -dmS script2 /usr/local/bin/script2_watcher
0 0 * * * touch /tmp/script1_enabled
15 */4 * * * touch /tmp/script2_enabled
bocian85
  • 812