如何将作业置于后台而不输出?

如何将作业置于后台而不输出?

当使用命令将作业置于后台时bg,我有作业命令的输出。

如何将作业置于后台(如bg命令)但没有任何输出?

>/dev/null 2>1PS:该作业链接到一个带有输出的命令(原始命令中没有)

答案1

您需要告诉现在后台的应用程序停止在 tty 设备上写入。没有通用的方法可以做到这一点。

你可以做:

stty tostop

使后台作业SIGTTOU在尝试写入 tty 时被挂起(用信号)。

您可以将调试器附加到进程并使其重新打开在 tty 设备上打开的文件描述符/dev/null。就像(这里仅用于标准输出):

gdb --batch -ex 'call close(1)' -ex 'call open("/dev/null",2)' -p "$pid"

(假设应用程序是动态链接的或具有调试符号,并注意某些系统将具有安全限制,阻止您执行此操作)。

对于动态链接的应用程序,您可以使用一个LD_PRELOADblob 来运行它们,该 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)。

相关内容