Elliott
Elliott

Reputation: 75

Disown, nohup or & on Mac OS zsh… not working as hoped

Hi. I'm new to the shell and am working on my first kludged together script. I've read all over the intertube and SO and there are many, MANY places where disown, nohup, & and return are explained but something isn't working for me.

I want a simpler timer. The script asks for user input for the hours, mins., etc., then:

echo "No problem, see you then…"
sleep $[a*3600+b*60+c]

At this point (either on the first or second lines, not sure) I want the script OR the specific command in the script to become a background process. Maybe a daemon? So that the timer will still go off on schedule even if

  • that terminal window is shut
  • the terminal app is quit completely
  • the computer is put to sleep (I realize I probably need some different code still to wake the mac itself)
  • Also after the "No problem" line I want a return command so that the existing shell window is still useful in the meantime.

    The terminal-notifier command (the timer wakeup) is getting called immediately under certain usage of the above (I can't remember which right now), then a second notification at the right time. Using the return command anywhere basically seems to quit the script.

    One thing I'm not clear on is whether/how disown, nohup, etc. are applicable to a command process vs. a script process, i.e., will any of them work properly on only a command inside a script (and if not, how to initialize a script as a background process that still asks for input).

    Maybe I should use some alternative to sleep?

    Upvotes: 3

    Views: 3057

    Answers (2)

    qqx
    qqx

    Reputation: 19475

    It isn't necessary to use a separate script or have the script run itself in order to get part of it to run in the background.

    A much simpler way is to place the portions that you want to be backgrounded (the sleep and following command) inside of parentheses, and put an ampersand after them.

    So the end of the script would look like:

    (
      sleep $time
      # Do whatever
    )&
    

    This will cause that portion of the code to be run inside a subshell which is placed into the background, since there's no code after that the first shell will immediately exit returning control to your interactive shell.

    Upvotes: 5

    ughoavgfhw
    ughoavgfhw

    Reputation: 39915

    When your script is run, it is actually run by starting a new shell to execute it. In order for you to get your script into the background, you would need to send that shell into the background, which you can't do because you would need to communicate with its parent shell.

    What you can do is have your script call itself with a special argument to indicate that it should do the work:

    #! /bin/zsh
    if [ "$1" != '--run' ] ; then
        echo sending to background
        $0 --run $@ &
        exit
    fi
    sleep 1
    echo backgrounded $@
    

    This script first checks to see if its first argument is --run. If it is not, then it calls itself ($0) with that argument and all other arguments it received ($@) in the background, and exits. You can use a similar method, performing the test when you want to enter the background, and possibly sending the data you will need instead of every argument. For example, to send just the number of seconds:

    $0 --run $[a*3600+b*60+c] &
    

    Upvotes: 0

    Related Questions