在后台静默启动任务

在后台静默启动任务

我知道您可以使用它在后台启动一个进程,而无需在该进程放入后台以及完成时收到通知,如下所示:

(命令 &) &> /dev/null

但是,这会删除进程完成时捕获的选项 ( trap child_done CHLD)。

我怎样才能两者兼得?

答案1

任务假脱机程序可能对你有帮助。

如在鲜肉网:

任务假脱机程序是一种 Unix 批处理系统,其中假脱机的任务一个接一个地运行。可以随时设置一次运行的作业量。每个系统中的每个用户都有自己的作业队列。这些任务在任何 shell/进程的正确上下文(入队上下文)中运行,并且可以轻松观看其输出/结果。当您知道您的命令依赖于大量 RAM、大量磁盘使用、提供大量输出,或者出于某种原因最好不要同时运行所有命令,而您想保留这些命令时,它非常有用。您的资源忙于实现最大效益。它的界面允许在脚本中轻松使用它。

任务后台处理程序可用于德班、Ubuntu 和其他发行版。

它允许您运行一个任务队列,并根据需要访问它们的输出。

例如:

$ tsp sleep 5
0 
$ tsp sleep 5 
1
$ tsp
ID   State      Output               E-Level  Times(r/u/s)   Command [run=1/1]
2    running    /tmp/ts-out.ZWn6Le                           sleep 5
1    finished   /tmp/ts-out.Fhlcle   0        5.00/0.00/0.01 sleep 5

如果你在后台运行很多作业,它肯定会对你有帮助。

您可以按顺序运行它们,也可以在预设数量的槽中运行它们。您还可以在任务之间建立依赖关系(运行任务1除非任务0成功完成)。

答案2

以下是在两者中执行此操作的方法{ba,z}sh

使用函数有助于不需要通过使用来保存和恢复变量zsh的状态。monitorsetopt local_options

# Run the command given by "$@" in the background
silent_background() {
  if [[ -n $ZSH_VERSION ]]; then  # zsh:  https://superuser.com/a/1285272/365890
    setopt local_options no_notify no_monitor
    "$@" &
  elif [[ -n $BASH_VERSION ]]; then  # bash: https://stackoverflow.com/a/27340076/5353461
    { 2>&3 "$@"& } 3>&2 2>/dev/null
  else  # Unknownness - just background it
    "$@" &
  fi
}

使用方法如下:

trap 'echo child done' CHLD
silent_background sleep 1

将产生预期的child done消息。

答案3

命令输出的重定向似乎无关紧要,因为通知已发送通过外壳当一个工作是异步启动的。更准确地说,它是与以下内容相关的 shell 功能(功能性)作业控制

这里引用来自“Bash 参考手册”,“作业控制”一章,第一节的内容。

shell 将一个作业与每个管道关联起来。它保存当前正在执行的作业的表,可以使用jobs命令列出该表。当 Bash 异步启动作业时,它会打印如下行:

[1] 25647

表示该作业的作业号为 1,并且与该作业关联的管道中最后一个进程的进程 ID 为 25647。单个管道中的所有进程都是同一作业的成员。 Bash 使用 JOB 抽象作为作业控制的基础。

请注意,shell 脚本不会显示此通知。

$ cat test
#!/bin/bash

true & echo true
$ ./test
true

据实

兹什

Zsh 文档提供了有关这些通知的类似指示,请参阅man 1 zshmisc“JOBS”部分。当以下情况时,不会显示这些通知:作业控制被禁用。

监视器-m,克什:-m

    允许作业控制。在交互式 shell 中默认设置。

zsh_prompt % setopt no_monitor
zsh_prompt % true & echo true
true
zsh_prompt %
zsh_prompt % 

重击

看来 Bash 总是显示例如[1] 25647。例如,“最终通知”[1]+ Done true在以下情况下不会显示:作业控制被禁用。

bash_prompt $ true & echo true
[1] 25647
true
bash_prompt $ 
[1]+  Done                    true

作业控制已禁用

bash_prompt $ set +m       # disable job control
bash_prompt $ true & echo true
[1] 25685
bash_prompt $
bash_prompt $

结论

不知道是否禁用作业控制隐藏通知是件好事吗?

资源

答案4

请参阅以下示例:

trap 'echo "DONE"' 0
{ find /usr & } &> /dev/null
wait

效果很好。不需要( ):这会产生一个不需要的子外壳。{ }只是分组命令。

相关内容