Gyan Veda Gyan Veda - 2 months ago 7
Linux Question

Schedule cron job to open Terminal and run command sequentially

I scheduled a cron job on a Mac to open Terminal every day at 11PM as follows:

0 23 * * * open -a Terminal

That works great! But what I would like is to not only open Terminal, but also to run a simple command within it. From looking online, it looks as if cron commands can be chained with

0 23 * * * open -a Terminal && echo 'Hello, world!'

However, this modified cron job only opens Terminal without running the second command there. Any thoughts on how I can get the cron job to do both?

pah pah

The following answer [after the separator] assumes that you want to run the second command within [inside] the Terminal. Otherwise you just need to swap the commands on your cronjob (because currently, as you have it, the echo will only execute after Terminal exits), such as:

0 23 * * * echo 'Hello, world!' && open -a Terminal

Now, assuming you want to run the command within the newly spawned terminal:

I'm not aware that Terminal application (from /Applications/Utilities/ accepts [i.e., interprets] any command line arguments nor will it read anything from [a standard output redirected to] standard input.

What you're doing with open -a Terminal && echo 'Hello, world!' is basically calling the Terminal application and [if successful] print 'Hello, world!' on the same shell that called the previous command (the Terminal). This is analogous to executing two separate commands in the same shell, but only executing the latest if the first succeeds.

If you want a specific command (say echo 'Hello, world!') to be executed every time bash (currently the default osx shell) is loaded for the current user (as in, every time the user opens a Terminal), you can add that command to ~/.bash_profile. For instance:

echo "echo 'Hello, world!'" >> ~/.bash_profile

Now when you open a Terminal, the command `echo 'Hello, world!'" will be executed.

Since the latest version of MacOSX does not include a ~/.bash_profile by default for any user, you can take advantage of this and change your crontab to:

0 23 * * * echo "echo 'Hello, world!' > ~/.bash_profile" && open -a Terminal

This basically will replace the contents of ~/.bash_profile for every time this crontab entry is executed and opens the Terminal.

The downside of doing that this way is that whatever you put inside ~/.bash_profile, will be executed for every opened Terminal, regardless of being the one from the crontab, or any other the user may open at any given time.

To solve this, you can also remove the ~/.bash_profile file from within it, by placing a trailing rm -f ~/.bash_profile command after the echo 'Hello, world!':

0 23 * * * echo "echo 'Hello, world!'; rm -f ~/.bash_profile" > ~/.bash_profile" && open -a Terminal

This will cause that when Terminal opens and calls bash, all the ~/.bash_profile commands will be executed, including the trailing rm -f ~/.bash_profile, so the next call to Terminal won't trigger your command again since the ~/.bash_profile no longer exists.

Sidenote: If, for some reason, you already have a ~/.bash_profile file, instead of replacing the whole contents of it and removing it after, you can backup the original, append your commands [including the one to restore the original file] and open the terminal. But I think this is not your case (anyway, if it is, I can extend this answer with the details).