Hitting Enter the script ends the process remains in the background.
Almost! Actually, the script has already exited by the time you press Enter. However, that's how you can get your prompt back (because your shell prints its $PS1
all over again).
The reason why hitting Ctrl + C terminates both of them is because the two of them are linked. When you execute your script, your shell initiates a subshell in which to run it. When you terminate this subshell, your background process dies, probably from a SIGHUP
signal.
Separate the script, the background process and the subshell
Using nohup
, you might be able to get rid of this little inconvenience.
#!/bin/sh
read -s -p "Enter Password: " pw
user=testuser
share=/fshare
cmd="sfk ftpserv -user=$user -pw=$pw -usedir $share=$share"
nohup $cmd &
The disown
alternative
If you can switch from /bin/sh
to /bin/bash
, you can give a try to disown
as well. To know more, just type help disown
in a bash
instance.
disown -h $cmd &
Killing the background process "nicely"
Now, when it comes to killing your process, you can perfectly do a "Ctrl + C" using kill
. Just don't send a brutal SIGKILL
. Instead, you could use:
$ kill -2 [PID]
$ kill -15 [PID]
Which will send a nice SIGINT
(2) or SIGTERM
(15) to your process. You may also want to print the PID value after starting the process:
...
nohup $cmd &
echo $!
... or even better, make the script wait for a SIGINT
, and send it back to the background process (this will keep your script in the foreground though):
#!/bin/sh
read -s -p "Enter Password: " pw
user=testuser
share=/fshare
cmd="sfk ftpserv -user=$user -pw=$pw -usedir $share=$share"
nohup $cmd &
# Storing the background process' PID.
bg_pid=$!
# Trapping SIGINTs so we can send them back to $bg_pid.
trap "kill -2 $bg_pid" 2
# In the meantime, wait for $bg_pid to end.
wait $bg_pid
If a SIGINT
isn't enough, just use a SIGTERM
instead (15) :
trap "kill -15 $bg_pid" 2 15
This way, when your script receives a SIGINT
(Ctrl + C, kill -2
) or a SIGTERM
while wait
ing for the background process, it'll just relay the signals to it. If these signals do kill the sfk
instance, then the wait
call will return, therefore terminating your script as well :)
Best Answer
Read from a pipe, write to a file
If you want the daemon to read input produced by some arbitrary process, you need to connect that process to a pipe. Here the arbitrary process is you echoing commands, and it's going to run in a different context. So create a named pipe (often called a fifo in unix contexts).
And just write commands to the pipe:
This is unlikely to work as is however: there's a good chance that the daemon will exit when it sees an end of file on its standard input, which happens as soon as the first process that writes to the pipe terminates. You can use
tail -f
to avoid that problem.With some
tail
implementations, you may get bitten by buffering: thetail
process will wait until it has amassed enough bytes to emit some output. I don't think this is solvable in the POSIX toolbox; if that's a problem, use a trivial C or Perl or Python program. As far as I can tell thetail
from GNU coreutils (as found on Linux and elsewhere) is safe on this respect.When you stop the daemon,
echo >/var/run/daemon.fifo
will kill thetail
process.Starting the program inside screen
Instead of invoking the daemon directly from your service manager (are you really using just SysV init, or something additional like wrapper scripts or Upstart?), invoke
Since the daemon won't be a child process of the service manager, you need to make sure to send a signal to the right process. How to do that depends on exactly how the daemon is started and by what.
It's technically possible to attach a running process to a terminal, but there's a risk you'll crash the program, so this is definitely out for a production system.
The
-L
option makes screen write everything that appears in its window to a file. The file name is given indaemon.screenrc
with thelogfile
directive.