You need to tell the now backgrounded application to stop writing on the tty device. There is no generic way to do that.
You can do:
stty tostop
to make so that background jobs be suspended (with a SIGTTOU
signal) when they try to write to the tty.
You can attach a debugger to the process and make it re-open the file descriptors it has open on the tty device to /dev/null
. Like (here for stdout only):
gdb --batch -ex 'call close(1)' -ex 'call open("/dev/null",2)' -p "$pid"
(assuming the application is dynamically linked or has debug symbols and note that some systems will have security restrictions preventing you from doing it).
For dynamically linked applications, you could run them with a LD_PRELOAD
blob that installs a handler on SIGTTOU (and do the stty tostop
) that reopens stdout and stderr on /dev/null
if they were going to a terminal. That would handle the case of non-setuid/setgid applications writing on the terminal via their stdout/stderr and don't handle SIGTTOU themselves.
Run:
gcc -Wall -shared -fPIC -nostartfiles -o ~/lib/handle_tostop.so handle_tostop.c
Where handle_tostop.c
contains:
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
static void reopen_on_null(int req_fd)
{
int fd;
if (close(req_fd) == 0) {
fd = open("/dev/null", O_RDWR);
if (fd != req_fd && fd >= 0) {
dup2(fd, req_fd);
close(fd);
}
}
}
static void handle_sigttou(int sig)
{
if (isatty(1)) reopen_on_null(1);
if (isatty(2)) reopen_on_null(2);
}
void _init()
{
signal(SIGTTOU, handle_sigttou);
}
And then:
LD_PRELOAD=~/lib/handle_tostop.so
export LD_PRELOAD
stty tostop
Instead of /dev/null
, you may want to redirect the output to some log file (which you might then want to open with O_APPEND
, and possibly include the pid of the process in the file name so you know whose process the output is from) so it's not discarded if it's of any use to you.
&> /dev/null
after they have already typed in the command, while also putting it inbg
. – Sparhawk Mar 13 '17 at 04:49