防止显示“[1] + did $scriptname”和“[1] 31303”

防止显示“[1] + did $scriptname”和“[1] 31303”

我为我的杂种狗设置了一个别名:alias mutt='$HOME/.mutt/run-notmuch-offlineimap & ; mutt'

笔记:将我的别名更改为alias mutt='$HOME/.mutt/run-notmuch-offlineimap 2> /dev/null & ; mutt'或 会alias mutt='$HOME/.mutt/run-notmuch-offlineimap 2>&1 >/dev/null & ; mutt'产生完全相同的结果。

该脚本run-notmuch-offlineimap看起来像这样:

#!/usr/bin/env zsh

notmuch="$(which notmuch)"

$notmuch new --quiet

$notmuch tag +inbox -- "folder:dev/dev|INBOX or folder:pers/pers|INBOX"
$notmuch tag +sent -- "folder:dev/dev|Sent or folder:pers/pers|Sent"
$notmuch tag +drafts -- "folder:dev/dev|Drafts or folder:pers/pers|Sent"
$notmuch tag +github -- "folder:dev/dev|github and not tag:github"


# test if the offlineimap instance of account dev is already running
if [[ $(pgrep -f 'offlineimap.*dev.*') == "" ]]
then
    offlineimap -c "$HOME/.fetch-send-mail/dev/dev.imap" -u quiet
fi


# test if the offlineimap instance of account dev is already running
if [[ $(pgrep -f 'offlineimap.*pers.*') == "" ]]
then
    offlineimap -c "$HOME/.fetch-send-mail/pers/pers.imap" -u quiet
fi

(如果我在此脚本中使用 bash,结果将完全相同)

当我开始 mutt 时,会发生以下情况:

~ 
$ mutt
[1] 31303
Mailbox is unchanged.
# some seconds afterwards:
~ 
$
[1]  + done       $HOME/.mutt/run-notmuch-offlineimap
~ 

消息“邮箱未更改”来自 mutt 本身,因此这是预期的。但是,我可以阻止[1]显示消息吗?例如,当我执行 mutt 时,它应该只打印此内容(而不打印其他内容):

~ 
$ mutt
Mailbox is unchanged.
~ 
$

我怎样才能做到这一点?

答案1

如果您在 zsh 中,则可以更改别名来启动后台进程,而&!不仅仅是&.这将立即否认的过程。

alias mutt='$HOME/.mutt/run-notmuch-offlineimap &! mutt'

如果您在 bash 中,那么您可以disown在命令后使用来获得类似的效果,但您仍然会收到列出 pid 的第一个作业控制消息。

alias mutt='$HOME/.mutt/run-notmuch-offlineimap & disown; mutt'

您可以通过使用子 shell 来避免这两种情况:

alias mutt='($HOME/.mutt/run-notmuch-offlineimap &); mutt'

答案2

解释

[1] + done <scriptname> ... [1] 31303由 shell (zsh)打印作业控制。这是使用 异步运行命令的结果&

在您的情况下,mutt是别名$HOME/.mutt/run-notmuch-offlineimap & ; mutt,因此run-notmuch-offlineimap是异步执行的,并且在启动和完成时将打印作业控制消息。

例子:

$ { sleep .3; echo; } &
[1] 71975
$

[1]  + 71975 done       { sleep .3; echo; }

可能的解决方案

取消设置MONITORshell 选项

$ unsetopt MONITOR  # or set +m
$ { sleep .3; echo; } &
# (no job control messages)

# reset the option:
$ setopt MONITOR  # or set -m

这将抑制作业控制消息。另请注意,该作业不会添加到作业表 ( jobs) 中。

从文档中:

  • 选项,16.2.7 作业控制:
    MONITOR (-m, ksh: -m)
    
        Allow job control. Set by default in interactive shells.
    
  • 10.1 工作
    If the MONITOR option is set, an interactive shell associates a 
    job with each pipeline. It keeps a table of current jobs, printed 
    by the jobs command, and assigns them small integer numbers. When 
    a job is started asynchronously with ‘&’, the shell prints a line 
    to standard error which looks like:
    
        [1] 1234
    

执行而&!不是&

异步命令将立即被拒绝并从作业表中删除。

$ { sleep .3; echo; } &!
# (no job control messages)

在子 shell 中执行异步命令本身

$ ({ sleep .3; echo; } &)
# (no job control messages)

(上面说明了这一点,但是异步运行没有多大意义,{..}因为(..)(子 shell 本身)不是异步运行的。因此完整的命令将被阻止。)

为什么在子 shell 中执行异步命令是否会抑制作业控制输出?因为:MONITOR子 shell 中未设置 shell 选项(无论父 shell 中的设置如何):

$ setopt monitor;
$ [[ -o monitor ]] && echo "SET" || echo "UNSET"
SET
$ ( [[ -o monitor ]] && echo "SET" || echo "UNSET" )
UNSET

其他选项

使用zsh/schedzsh 模块,或外部脚本,例如zsh-defer或者zsh-async

相关内容