Reputation: 2115
What I am trying to do is write a Bash script that sleeps for a set amount of time before using the mac say command to speak some text.
I'd like to be able to run the command and then close the terminal so it will still speak at the set time. I've looked into nohup, detach, launchd, and putting the process in the background, but all of these solutions still result in the process being terminated once the terminal is closed. Should I somehow make some sort of zombie child process to do this? What is the best solution? Thank you
# Simple Example of main code
sleep 10;
say hello;
exit;
Upvotes: 18
Views: 30691
Reputation: 2412
All the solution here are very good, but they don't provide an easy way to "look" what happen in the program without doing a redirection that would fill the hard drive.
Using screen
you can then very easily run a script, close your terminal/ssh session, and then come back latter, and "attach" again to the script. Do do that it's pretty easy.
First install screen
:
sudo apt-get install screen
and then put in your bash file
#!/usr/bin/env bash
screen -S myscreen -d -m bash -c 'ls; exec bash'
(replace ls
with your program) It will create (-S
) a "screen" named myscreen
, and detach it (-d
) by running the commands inside the ``-c``` option. Then if you want to connect later to this screen:
screen -rd myscreen
if you want to list all screen currently running:
screen -ls
NB: if you want to close the screen when it's finished, remove the bash
at the end of the command.
Upvotes: 1
Reputation: 26096
Depending on your definition of 'easy' the answer may be daemon.
Upvotes: 0
Reputation: 92772
nohup yourscript.sh 10 "hello" &
# ^your script ^^your parameter 1
# ^^^^^^^your parameter 2
This will detach the script from the terminal, and it won't be killed when the terminal closes. Note the &
at the end; you can pass parameters to your script normally. Then yourscript.sh could be:
#!/bin/bash
sleep $1;
say "$2";
exit;
Upvotes: 13
Reputation: 360315
Your script could look like this:
#!/bin/bash
read -p "Text: " text
read -p "Delay: " delay
nohup bash -c "sleep $delay; say \"$text\" &"
Then you would run your script normally:
$ your_script
Text: hello
Delay: 10
and the outer script would exit, but the Sleep&Say™
would be left running in the background.
Upvotes: 3
Reputation: 47193
Use nohup yourscript.sh &
as Piskvor suggested.
However, note that you won't be able to regain "control" of your process. Therefore, if you do need it, I suggest adding logging to a file so you know what your program is doing.
Killing your program might not be possible without kill -9
, and that might be a bit brutal. If you don't want that, I'd suggest pooling for a file like end.txt
every minute or so. If your program detects presence of such a file in it's working directory, it should exit gracefully.
Upvotes: 0
Reputation: 3660
If you do not start it with nohup
, as already suggested, you would need to use disown
as such ...
$ ./say-hello.sh &
[1] 12345
$ disown -h %1
You will need to make note of the job number (the second line in the example above, the job number is in the brackets and the other is the process id) so that you can pass it to disown
.
Upvotes: 6
Reputation: 754420
Section 3.7.6 of the Bash Manual says:
The shell exits by default upon receipt of a SIGHUP. Before exiting, an interactive shell resends the SIGHUP to all jobs, running or stopped. Stopped jobs are sent SIGCONT to ensure that they receive the SIGHUP. To prevent the shell from sending the SIGHUP signal to a particular job, it should be removed from the jobs table with the disown builtin (see Section 7.2 [Job Control Builtins], page 88) or marked to not receive SIGHUP using
disown -h
.
So, using either nohup
or disown
should do the trick. Or you can do:
trap "" 1
sleep 10
say hello
That 'trap
' line ignores signal 1, SIGHUP; you can probably also write 'trap "" HUP
".
Upvotes: 14
Reputation: 143264
You need to use nohup and background together. I just tried this on OS-X to verify that it works:
nohup ./say-hello.sh &
Upvotes: 6