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.
Share
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
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.
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
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.
If you'd like to try out Dropbox, use this link to get some extra quota:
http://www.dropbox.com/referrals/NTI0NDI4OTE5
@Many - I stand corrected about the need to reboot.
Thanks for the insights. My knowledge of launchd was obviously outdated.
"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'.
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">
<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>
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">
<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>
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">
<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>
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.
"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...
Deals of the Day
more deals- Cases for New iPad at HandHeldItems: Extra 20% off, $2 credit, from $3 + $3 s&h
- $15 Apple iTunes Gift Card for $8 for new Saveology customers
- Philips Fidelio Docking Speaker Station for iPhone / iPod for $38 + $6 s&h
- Retro 80's Case for iPhone for $11 + $2 s&h
- HHI 360 Dual-View Stand Case for new iPad w/ $2 credit for $12 + $3 s&h
- HHI ReElegant Smart Cover Companion Case for new iPad from $5 + $3 s&h
37 Comments