11

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?

Gyan Veda
  • 6,309
  • 11
  • 41
  • 66

3 Answers3

6

Great answers already provided by pah and Sameer Naik, but I ended up going with an even simpler solution using AppleScripts, inspired by an SO answer to a similar question.

0 23 * * * osascript -e 'tell application "Terminal" to do script "echo \"Hello, world\"!"'
Community
  • 1
  • 1
Gyan Veda
  • 6,309
  • 11
  • 41
  • 66
  • Very interesting solution :) – pah Aug 07 '16 at 14:32
  • Just my personal observation on SO so far. Many people think termimal to be an application that lets you execute some obscure commands. But it merely exposes you to UNIX shell command prompt. There are other terminal softwares like iTerm2 that do the same function. So IMHO, using a shell script invoked via cron is simplest, but I understand that "simpler" depends on everyone's comfort level. – Sameer Naik Aug 07 '16 at 18:48
  • Not sure what you mean by obscure commands, Terminal is pretty straightforward. One line of code seems preferable to a new file. Not really about comfort level, more about practicality. – Gyan Veda Aug 08 '16 at 17:23
  • 1
    This is much cleaner than continually editing the bash_profile, nice idea. – Josh Correia Jun 24 '19 at 15:01
3

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/Terminal.app/Contents/MacOS/Terminal) 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).

pah
  • 4,700
  • 6
  • 28
  • 37
1

You can create a script say my_cron_job.sh and execute it via cron 0 23 * * * my_cron_job.sh Specify absolute path to the script e.g. /users/your_user_name/scripts/my_cron_job.sh

Sameer Naik
  • 1,326
  • 1
  • 13
  • 28