当使用命令将作业置于后台时bg
,我有作业命令的输出。
如何将作业置于后台(如bg
命令)但没有任何输出?
>/dev/null 2>1
PS:该作业链接到一个带有输出的命令(原始命令中没有)
答案1
您需要告诉现在后台的应用程序停止在 tty 设备上写入。没有通用的方法可以做到这一点。
你可以做:
stty tostop
使后台作业SIGTTOU
在尝试写入 tty 时被挂起(用信号)。
您可以将调试器附加到进程并使其重新打开在 tty 设备上打开的文件描述符/dev/null
。就像(这里仅用于标准输出):
gdb --batch -ex 'call close(1)' -ex 'call open("/dev/null",2)' -p "$pid"
(假设应用程序是动态链接的或具有调试符号,并注意某些系统将具有安全限制,阻止您执行此操作)。
对于动态链接的应用程序,您可以使用一个LD_PRELOAD
blob 来运行它们,该 blob 在 SIGTTOU 上安装一个处理程序(并执行),如果它们要访问终端,则stty tostop
重新打开 stdout 和 stderr 。/dev/null
这将处理非 setuid/setgid 应用程序通过其 stdout/stderr 在终端上写入的情况,并且本身不处理 SIGTTOU。
跑步:
gcc -Wall -shared -fPIC -nostartfiles -o ~/lib/handle_tostop.so handle_tostop.c
其中handle_tostop.c
包含:
#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);
}
进而:
LD_PRELOAD=~/lib/handle_tostop.so
export LD_PRELOAD
stty tostop
而不是/dev/null
,您可能希望将输出重定向到某个日志文件(然后您可能希望使用 来打开该日志文件 O_APPEND
,并且可能在文件名中包含进程的 pid,以便您知道输出来自谁的进程),这样它就不会被丢弃如果它对你有任何用处。
答案2
如果你使用诺哈普您的作业将在后台运行,但这会创建自动输出(nohup.out)。