I have written a script that relies on other server responses (uses
wget to pull data), and I want it to always be run in the background unquestionably. I know one solution is to just write a wrapper script that will call my script with an
& appended, but I want to avoid that clutter.
Is there a way for a bash (or zsh) script to determine if it was called with say
./foo.sh &, and if not, exit and re-launch itself as such?
The definition of a background process (I think) is that it has a controlling terminal but it is not part of that terminal’s foreground process group. I don’t think any shell, even zsh, gives you any access to that information through a builtin.
On Linux (and perhaps other unices), the
STAT column of
ps includes a
+ when the process is part of its terminal’s foreground process group. So a literal answer to your question is that you could put your script’s content in a
main function and invoke it with:
case $(ps -o stat= -p $$) in
*+*) main "[email protected]" &;;
*) main "[email protected]";;
But you might as well run
main "[email protected]" & anyway. On Unix, fork is cheap.
However, I strongly advise against doing what you propose. This makes it impossible for someone to run your script and do something else afterwards — one would expect to be able to write
your_script; my_postprocessing or
your_script && my_postprocessing, but forking the script’s main task makes this impossible. Considering that the gain is occasionally saving one character when the script is invoked, it’s not worth making your script markedly less useful in this way.
If you really mean for the script to run in the background so that the user can close his terminal, you’ll need to do more work — you’ll need to daemonize the script, which includes not just backgrounding but also closing all file descriptors that have the terminal open, making the process a session leader and more. I think that will require splitting your script into a daemonizing wrapper script and a main script. But daemonizing is normally done for programs that never terminate unless explicitly stopped, which is not the behavior you describe.
I do not know, how to do this, but you may set variable in parent script and check for it in child:
if [[ -z "$_BACKGROUNDED" ]] ; then
_BACKGROUNDED=1 exec "$0" "[email protected]" & exit
# Put code here
Works both in bash and zsh.
the “tty” command says “not a tty” if you’re in the background, or gives the controlling terminal name (/dev/pts/1 for example) if you’re in the foreground. A simple way to tell.
Remember that you can’t (or, not recommended to) edit the running script. This question and the answers give workarounds.
I don’t write shell scripts a long time ago, but I can give you a very good idea (I hope). You can check the value of $$ (this is the PID of the process) and compare with the output of the command “jobs -l”. This last command will return the PID of all the backgrounded processes (jobs) and if the value of $$ is contained in the result of the “jobs -l”, this means that the current script is running on background.