Você precisa dizer ao aplicativo agora em segundo plano para parar de escrever no dispositivo tty. Não há uma maneira genérica de fazer isso.
Você pode fazer:
stty tostop
para que as tarefas em segundo plano sejam suspensas (com um sinal SIGTTOU
) quando tentarem escrever no tty.
Você pode anexar um depurador ao processo e fazê-lo reabrir os descritores de arquivo que ele abriu no dispositivo tty para /dev/null
. Like (aqui apenas para stdout):
gdb --batch -ex 'call close(1)' -ex 'call open("/dev/null",2)' -p "$pid"
(assumindo que o aplicativo esteja vinculado dinamicamente ou tenha símbolos de depuração e observe que alguns sistemas terão restrições de segurança que o impedem de fazê-lo).
Para aplicativos vinculados dinamicamente, você pode executá-los com um LD_PRELOAD
blob que instala um manipulador em SIGTTOU (e faz o stty tostop
) que reabre stdout e stderr em /dev/null
se eles estivessem indo para um terminal. Isso lida com o caso de aplicações não-setuid / setgid que escrevem no terminal através do seu stdout / stderr e não lidam com o próprio SIGTTOU.
Executar:
gcc -Wall -shared -fPIC -nostartfiles -o ~/lib/handle_tostop.so handle_tostop.c
Onde handle_tostop.c
contém:
#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);
}
E então:
LD_PRELOAD=~/lib/handle_tostop.so
export LD_PRELOAD
stty tostop
Em vez de /dev/null
, talvez você queira redirecionar a saída para algum arquivo de log (que talvez queira abrir com O_APPEND
e possivelmente incluir o pid do processo no nome do arquivo para saber qual processo a saída é de) por isso não é descartada se for de alguma utilidade para você.