在后台静默启动任务


12

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

(命令&)&> / dev / null

但是,这删除了在过程结束时进行陷阱的选项(trap child_done CHLD)。

我怎么都可以?

Answers:


5

任务假脱机程序可能会帮助您。

如在freshmeat.net中

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

Task-spooler在Debian,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

如果您在后台运行大量工作,那一定会对您有所帮助。

您可以按顺序运行它们,也可以按预设的插槽数量运行它们。您也可以建立任务之间的依赖关系(运行TASK1只有task0成功完成)。


3

这两种方法都是这样做的{ba,z}sh

使用功能可以不需要保存和恢复状态zshmonitor使用的变量setopt local_options

# Run the command given by "$@" in the background
silent_background() {
  if [[ -n $ZSH_VERSION ]]; then  # zsh:  /superuser//a/1285272/365890
    setopt local_options no_notify no_monitor
    "$@" &
  elif [[ -n $BASH_VERSION ]]; then  # bash: /programming//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消息。


请参阅unix.stackexchange.com/q/456549/4778,以获得有希望的解释。
ctrl-alt-delor

2

命令输出的重定向似乎无关紧要,因为在异步启动作业时,通知是由Shell发送。更确切地说,它是与作业控制相关的外壳功能(功能性)。

在此,引自《 Bash参考手册》第一章“作业控制”。

Shell将JOB与每个管道关联。它保留一个当前正在执行的作业的表,该表可能随jobs命令列出。当Bash异步启动作业时,它会打印一条类似于以下内容的行:

[1] 25647

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

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

$ cat test
#!/bin/bash

true & echo true
$ ./test
true

据实

sh

Zsh文档提供了有关这些通知的类似指示,请参见man 1 zshmisc“作业”部分。禁用作业控制时,不会显示这些通知。

监视器-m,ksh:-m

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

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 $

结论

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

资源资源


1

您可以zsh作为非交互式shell 调用以禁用作业通知。

zsh -c '
   trap "echo trapped child_done" CHLD
   sleep 5 &
   #wait
   sleep 10 # simulate other running cmds
   echo script done
'

0

请参见以下示例:

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

那很好。不需要( ):这使得不需要的子shell。{ }只是对命令进行分组。


那会打印[2] 49591[2] + 49591 exit 1 find /usr,什么时候它们都不应该打印!
蒂洛2012年

抱歉,这样会误解您的问题。
吉尔斯·奎诺

0

这是一个老问题,但是一个可能的答案(在bash中,未经zsh测试)是在子shell中使用job控件: (command & wait)

注意:bash禁止子外壳中的开始/结束后台作业消息,因此不需要重定向。


我想你错过了陷阱的一部分。据我所知,应该启动子流程的问题,在执行supprocess时将执行某些操作,然后在子流程完成时应执行其他操作。使用您的解决方案,您可以在子外壳程序中启动子进程并等待它,而主外壳程序则在等待子外壳程序。这样可以消除消息,但是您不能并行执行某些操作。
拉斐尔·阿伦斯

不,(sleep 5 & wait)延迟5秒。
汤姆·黑尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.