zsh 中的静默后台作业

zsh 中的静默后台作业

我跑弓箭在我的 .zshrc 中。问题是,由于显示当前 IP,它有时会运行两秒钟。为了使它不那么引人注目,我把它放在后台,如下所示:

# .zshrc
archey &
# lots of foo
wait

这样,它可以获取 IP,同时在我的 zshrc 中完成许多其他工作。但现在 zsh 每次都会显示作业和进程 ID,并且 archey 已完成:

Last login: Mon Jul 10 11:12:07 on ttys002
[1] 40436

# archey output

[1]  + done       archey

~

由于文档指出这将被发送到 stderr,我尝试使用 2>/dev/null,但没有成功。

我怎样才能删除这两行?

答案1

Zsh 提供MONITORNOTIFY选项,您可以禁用它们以静音后台作业的状态报告。

() {
  setopt LOCAL_OPTIONS NO_NOTIFY NO_MONITOR
  archey &
  # ...
  wait
}

答案2

如果你不想使用子shell,你可以使用:

# 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
    # We'd use &| to background and disown, but incompatible with bash, so:
    "$@" &
  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
  disown &>/dev/null  # Close STD{OUT,ERR} to prevent whine if job has already completed
}

然后:

silent_background archey #  Or whatever command you want to background

答案3

这应该不需要额外的脚本文件:

tmpf=`mktemp`
{ archey ; echo 1 > "$tmpf" ; } &|

# foo

while [ ! -s "$tmpf" ] ; do sleep 0.1 ; done
rm "$tmpf"
unset tmpf

关键是&|操作符。它在后台运行给定的命令,但该命令不是作业,因此您的显示不会被垃圾邮件淹没。您无法使用wait。我使用了一个临时文件来检测是否archey已完成。

如果你# foo也生成输出,则可能会遇到竞争条件。在这种情况下,将archey输出捕获到另一个临时文件(如在另一个答案中) 并将其打印在末尾。

我不建议使用单个临时文件进行archey输出和触发器。我认为,如果你这样做,当仍然写入文件时,while测试可能会返回 true 。archey

答案4

这两行是 shell 的输出stderr,而不是进程的输出。您无法让它们从 zsh 中消失。

从评论中意识到,您想要看到显示的输出,您需要执行三个步骤:

  1. 为了避免在后台启动 archey 的噪音,您必须从脚本启动它
  2. 要将 archey 的结果传回主脚本,您必须使用临时文件或类似的东西
  3. 要理解,当它完成时,你不能使用,wait因为它取决于嘈杂的背景开始

wrap-archey.sh:

#/bin/sh
archey >"$1" 2>&1
rm "$2"

启动-archey.sh:

/path/to/wrap-archey.sh "$1" "$2" >/dev/null 2>&1 &

.zshrc:

ARCHEYOUT=$(mktemp)
ARCHEYFLAG=$(mktemp)
/path/to/start-archey.sh "$ARCHEYOUT" "$ARCHEYFLAG" >/dev/null 2>&1
#
# lots of foo
#
while test -f "$ARCHEYFLAG"; do sleep 0.1 ; done
cat "$ARCHEYOUT"
rm "$ARCHEYOUT"

wrap-archey.sh 将把输出重定向到临时文件,完成后删除标志文件。这对于后台通信是必需的。

start-archey.sh 将在后台启动 wrap-archey.sh,消除主脚本中的噪音并立即返回。

.zshrc 将设置 flagfile 和 resultfile,在后台静默运行 start-archey.sh,然后执行 foo,然后通过轮询 flagfile 等待 archey 完成。然后清理。

相关内容