Skip to Content

Terminal Tips: bash cron script to keep an app running

Do you have some apps that you want to keep running all the time? If so, and if you're not afraid of the Terminal or the command line, I have a script for you.

When I come home at the end of the day, Dropbox has stopped running on my iMac. I'm running the latest version, and it works fine on my MacBook Pro, but for some reason, this just keeps happening. The script has nothing to do with Dropbox itself; you could substitute any app that you always want running, such as LaunchBar, OmniFocus, 1Password, or any other app that you like.

It's fairly simple:

#!/bin/sh

PATH=/bin:/usr/bin

# Change 'Dropbox' to whatever app you want. Be sure to capitalize
# it correctly and include any spaces. You do not need to add .app
APPNAME="Dropbox"

# if the app name _IS_ found in process list, exit
ps xc|fgrep "${APPNAME}" >/dev/null && exit 0

# if the app isn't found, open it
open -a "${APPNAME}"

exit 0

That's it. Now, you save the file (I call mine "keep-my-app-running.sh"); I saved it to ~/bin/, but you can put it anywhere you want.

Be sure to type 'chmod +x /Users/luomat/bin/keep-my-app-running.sh' (or wherever it is saved) to tell OS X it is an eXecutable file. (Thanks to Justin for reminding me about this in the comments below.)

Now, we need to tell cron to run it. Some folks will tell you to use launchd, but cron works well and it's easy, so we'll use that. To do that, create a ~/.crontab file using your favorite text editor. If it already exists, just keep whatever's there, and add this line at the bottom:

*/5 * * * * /Users/luomat/bin/keep-my-app-running.sh

Change "luomat" to whatever your login name is, and change "keep-my-app-running.sh" to whatever you named the script. This tells cron to check if your app is running every 5 minutes or so. You can change the 5 to something else if you want to change the frequency. The last step is to tell cron to load the new file you've created:

crontab ~/.crontab

If you want to verify that it worked, run 'crontab -l' to see if your crontab is listed properly. It may also be a good idea to run 'crontab -l' before you begin in order to make sure that there isn't anything already in there. Most likely there isn't, or if there is, you already know about it.

Update: As noted in the comments, cron works fine, but launchd can be configured to relaunch Dropbox as soon as it exits. I've enclosed a picture of a Lingon screenshot below, or you can see the plist that it creates. Lingon is no longer developed, but it works fine for me under Snow Leopard.

I tried to use launchd to run a script at 0, 15, 30, and 45 minutes past the hour, which I can do in cron using this:

*/15 * * * * /path/to/script.sh

but launchd didn't keep that schedule (for example, it posted at 11:48 and 12:03). So I decided to keep using cron for that, although launchd is a much better option for the 'keep alive' purpose.



Categories

Mac OS X

Do you have some apps that you want to keep running all the time? If so, and if you're not afraid of the Terminal or the command line, I...
 

Add a Comment

*0 / 3000 Character Maximum Comment Moderation Enabled. Your comment will appear after it is cleared by an editor.

37 Comments

Filter by:
rampantsolutions

A better .plist example:





Label
com.example.exampled
ProgramArguments

exampled

KeepAlive




http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man5/launchd.plist.5.html

AppleTV will not stream if iTunes is not running. I use a variant of this script to keep it running if I inadvertently quit the program.

October 26 2010 at 11:41 AM Report abuse rate up rate down Reply
chakatns

Great comments!
Do you guys know how to shorten terminal command, and give it a letter?

For instance I often use whois command via terminal and would like to type w and than domain name to get whois output.

Thank you!

//Rob

October 26 2010 at 5:10 AM Report abuse rate up rate down Reply
1 reply to chakatns's comment
TJ Luoma


That depends what shell you are using. Assuming you are using a bash variant (including zsh/ksh/etc) you should be able to do that with

alias w='whois'

(You'll need to put that into the startup file for whatever shell you use.)

however, there is already a 'w' command (/usr/bin/w) so you might want to consider giving your shortcut another name.

October 26 2010 at 11:54 AM Report abuse rate up rate down Reply
Sejuru

If you'd like to try out Dropbox, use this link to get some extra quota:

http://www.dropbox.com/referrals/NTI0NDI4OTE5

October 25 2010 at 8:36 PM Report abuse rate up rate down Reply
TJ Luoma

@Many - I stand corrected about the need to reboot.

Thanks for the insights. My knowledge of launchd was obviously outdated.

October 22 2010 at 11:02 AM Report abuse rate up rate down Reply
alrescha20

"Lingon is not wrong about needing to restart or logout, I've tested that for myself."

So apparently you've never tried 'launchctl load plistfile'?

Thanks to patg for the other examples.

I'll now transition from 'random commenter on the internet' back to 'random reader of the internet'.

October 21 2010 at 11:42 PM Report abuse rate up rate down Reply
Pat Gavlin

Seems like my last couple of comments got lost. Here's a launchd plist without any absolute paths:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
<plist version="1.0">
<dict>
<key>Label</key>
<string>local.keep_dropbox_running</string>
<key>ProgramArguments</key>
<array>
<string>open</string>
<string>-W</string>
<string>-a</string>
<string>Dropbox</string>
</array>
<key>KeepAlive</key>
<true />
<key>RunAtLoad</key>
<true />
</dict>
</plist>

October 21 2010 at 10:17 PM Report abuse rate up rate down Reply
Pat Gavlin

Should be:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
<plist version="1.0">
<dict>
<key>Label</key>
<string>local.keep_dropbox_running</string>
<key>ProgramArguments</key>
<array>
<string>open</string>
<string>-W</string>
<string>-a</string>
<string>Dropbox</string>
</array>
<key>KeepAlive</key>
<true />
<key>RunAtLoad</key>
<true />
</dict>
</plist>

October 21 2010 at 10:10 PM Report abuse rate up rate down Reply
Pat Gavlin

There also happens to be an absolute path right here:
*/5 * * * * /Users/luomat/bin/keep-my-app-running.sh



Here's a launchd plist that should achieve the same without any absolute paths:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
<plist version="1.0">
<dict>
<key>Label</key>
<string>local.keep_dropbox_running</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/open</string>
<string>-W</string>
<string>-a</string>
<string>Dropbox</string>
</array>
<key>KeepAlive</key>
<true />
<key>RunAtLoad</key>
<true />
</dict>
</plist>

October 21 2010 at 10:09 PM Report abuse rate up rate down Reply
Pat Gavlin

The Program key in a launchd plist has the same semantics as execvp. From the launchd.plist manpage:

Program
This key maps to the first argument of execvp(3). If this key is missing,
then the first element of the array of strings provided to the
ProgramArguments will be used instead.

According to the execvp manpage, a call to execvp uses the PATH environment variable if it is set. Otherwise, it searches /usr/bin and /bin. The absolute path is necessary because the directory containing the actual executable for a given application (usually /Contents/MacOS/) is unlikely to be in a user's PATH. Even if it were, it's possible that a user's PATH hasn't been set when launchd loads a given job (e.g. if .bash_profile is not read until after all launchd jobs have been loaded).

On another note, a big downside of the script above is that it cannot check the exit status of the application it is keeping alive. In other words, you cannot reliably quit an application (if you need to) without disabling the cron job.

Here are a couple of scripts that generate/install launchd jobs to relaunch a given application or executable if it exits unsuccessfully:

http://www2.uic.edu/~pgavli2/keep-running.sh
http://www2.uic.edu/~pgavli2/gen-keepalive-plist.sh

So long as an application is guaranteed to exit with a non-zero status when it crashes, these jobs should operate properly.

October 21 2010 at 8:31 PM Report abuse rate up rate down Reply
alrescha20

"Lingon recommends", "Select an app in Lingon", etc.

Apparently you think 'Lingon = launchd". Lingon is an abandoned third-party GUI for editing launchd plists. It's a nice tool, but it's NOT launchd.

"The only way to manage it via ssh would be to edit XML plist by hand. Can it be done? Yes. It is fraught with peril and easy to screw up? Yes."

And you've never screwed up a crontab entry? Tell me, without looking, which column is for 'day of the week'?

Sheesh, talk about zealotry...

October 21 2010 at 11:01 AM Report abuse rate up rate down Reply
3 replies to alrescha20's comment
Buy an ad here

Tweets

© 2012 AOL Inc. All Rights Reserved.