“使”符号“可变”(后台处理)


9

我想知道是否有办法将&符放入变量中,并仍然使用它来将进程发送到后台。

这有效:

BCKGRND=yes
if [ "$BCKGRND" = "yes" ]; then
    sleep 5 &
else
    sleep 5
fi

但是,仅用一条完成这五条线不是很酷吗?像这样:

BCKGRND='&'
sleep 5 ${BCKGRND}

但这是行不通的。如果未设置BCKGRND,则它可以工作-但是,如果设置了BCKGRND,则将其解释为文字'&'并输出错误。


使用结尾的&符号后,echo $!返回PID
noobninja

Answers:


9

无法使用变量在后台调用,因为变量扩展是在为控件运算符(例如&&&)解析命令行后发生的。

还有一种选择是将调用包装在一个函数中:

mayberunbg() {
  if [ "$BCKGRND" = "yes" ]; then
    "$@" &
  else
    "$@"
  fi
}

...然后根据需要设置变量:

$ BCKGRND=yes mayberunbg sleep 3
[1] 14137
$
[1]+  Done                    "$@"
# or
$ BCKGRND=yes
$ mayberunbg sleep 3
[1] 14203
$
[1]+  Done                    "$@"
$ BCKGRND=no mayberunbg sleep 3
# 3 seconds later
$

什么,没有ed?无论如何+1,这是最干净的解决方案。
斯蒂芬·基特

哈哈@StephenKitt; 现在齿轮正在转动
杰夫·谢勒

我喜欢eval答案的简单性,但是我想作为背景的实际命令却过于复杂,其中包含太多变量,因此无法使用eval。@ jeff-schaller给出的答案向我指出了前进的方向。不过,我将整个命令放在一个变量中,而不是一个函数,然后使用他的if语句样式执行带或不带&的命令。
BrowncoatOkie,

11

您可以翻转事物并改变“前景”:

FOREGROUND=fg
sleep 5 & ${FOREGROUND}

设置FOREGROUNDtrue或为空可在后台运行该进程。(设置FOREGROUNDtrue在后台运行是令人困惑的!留给读者适当的变量名作为练习。)


4
很好,但是如果没有作业控制(例如,除非set -m使用任何脚本),否则无法在Shell中运行。
mosvy

9

您可能必须使用eval

eval "sleep 5" "$BCKGRND"

eval使外壳重新评估给定的参数。&因此,文字将被解释为&命令的末尾而不是命令的参数,从而将命令置于后台。


2
eval包含的答案应包含警告,请谨慎处理。参见例如这个答案
拉尔夫

我不明白计算"$BCKGRND"一个空参数是什么问题。
mosvy

2
@Ralf 在这种情况下绝对无关紧要。eval没什么特别的-例如,您可以通过算术扩展执行命令。也许应该有这样的警告,根本禁止使用bash(或任何类似的shell);-)
mosvy

1
@Kusalananda eval将在进行实际评估之前将其参数与空格连接。尝试一下:eval printf "'{%s}\n'" foo "" "" ""eval foo "" "" "" ""完全类似于eval foo,无论是什么IFS或其他事物。
mosvy

1
评估的命令如果包含任何特殊字符(例如),则应用双引号引起来eval 'sleep $TIMEOUT' "$BACKGROUND"。否则,如果变量扩展到另一个变量或包含特殊字符,则可能会出现双倍扩展。而且,嵌套引用可能会很棘手。
Barmar
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.