The iPhone has a launch timeout built into the system. When an app launches, it isn't supposed to start processing data right away, it is simply supposed to load whatever it needs then make a C++ call to the system saying it finished launching. This call is aptly named applicationDidFinishLaunching. If the system doesn't get that call, it assumes the app failed to launch and kills it.
The same thing happens when you launch a shell script from a SpringBoard icon. This script will not work:
#! /bin/shThis is meant to pop up a notification every ten seconds but after approximately 18 seconds, the system kills it because it did not receive the applicationDidFinishLaunching call.
uiopen start
sleep 10s
uiopen ten
sleep 10s
uiopen twenty
sleep 10s
uiopen thirty
Some jailbreak apps have a way around this. I emailed BigBoss a few months ago and asked if he knew of a way around the launch timeout with a script, and he pointed me to the method SBSettings uses. SBSettings does not actually launch itself, it instead uses a small shell script to launch the real SBSettings executable:
SBSettings=$(dirname "$0")What this does is pretty simple. The script uses the first line to find itself on the system, the second line launches SBSettings, which it expects to find in the same directory. It launches with the exec command, which replaces the current shell with whatever exec executes.
exec "${SBSettings}"/SBSettings
Unfortunately, I had already tried this and could never get it to work with a shell script. I've also tried every other method I could think of to background a script such as using the standard "&" tacked on to the command or trying the disown command. These would probably work in MobileTerminal, but nothing seemed to work when launching a script from SpringBoard.
You may be able to use launchd to run a longer script, but I wanted to do it on the fly. I only had one long script I wanted to use and simply gave up on it and forgot about it until an unlikely answer came to me while working on an unrelated problem. Why not see what happens when you ssh in to localhost and run the script?
Well, you can't simply ssh in and run the command or the ssh pipe will stay open. This is a feature of OpenSSH used to avoid a race condition. To background it, you have to redirect sdtin, stdout and stderr to a file or, as I used here, to /dev/null.
slogin -i ~/.ssh/KEY localhost '/Applications/test.app/test_ </dev/null >/dev/null 2>&1 &'To my surprise, that actually works. This command can be put in /Applications/test.app/test and launched from SpringBoard. It will then ssh to localhost and successfully launch and background test_, which can run as long as it wants.