【问题标题】:Different results when running commands in braces within a bash script在 bash 脚本中运行大括号中的命令时的不同结果
【发布时间】:2017-01-14 16:41:46
【问题描述】:

我正在编辑一个脚本,由于脚本有点长,我决定将脚本的主要部分用大括号括起来,并将输出转移到一个日志文件,而不是为命令单独重定向日志。然后我注意到检查脚本的运行副本的命令块会给出 2 个不同的结果,具体取决于它是否包含在大括号中。

我将脚本运行为:

$ /bin/bash scriptname.bash

我的问题是为什么同一个命令块会返回 2 个不同的结果,以及是否可以让命令块在大括号内工作。

下面是命令方块:

#!/bin/bash
#set -x   # Uncomment to debug this shell script
#
##########################################################
#         DEFINE FILES AND VARIABLES HERE
##########################################################
THIS_SCRIPT=$(basename $0)
TIMESTAMP=$(date +%Y-%m-%d_%H%M%S)
LOGFILE=process_check_$TIMESTAMP.log

##########################################################
#               BEGINNING OF MAIN
##########################################################

{
printf "%s\n" "Checking for currently runnning versions of this script"

MYPID=$$ # Capture this scripts PID
MYOTHERPROCESSES=$(ps -ef | \grep $THIS_SCRIPT | \grep -v $MYPID | \grep -v grep | awk '{print $2}')

if [[ "$MYOTHERPROCESSES" != "" ]]
  then
    printf "%s\n" "ERROR: Another version of this script is running...exiting!"
    exit 2
  else
    printf "%s\n" "No other versions running...proceeding"
fi

printf "%s\n" "Doing some script stuff..."
exit 0

} | tee -a $LOGFILE 2>&1
# End of script

【问题讨论】:

  • 你的输出有什么不同?您能否显示结果或差异。
  • 旁注:如果你想同时记录标准输出错误,stderr的重定向必须在管道之前发生(或者使用@ 987654323@ 用于管道)。
  • @Klaus - 在大括号中,该块显示有另一个脚本正在运行。在大括号之外时,该块正确评估没有其他副本正在运行。
  • @BenjaminW。 - 感谢那。在我的完整脚本中,我将错误代码分配给各个块,然后捕获这些代码并根据错误执行不同的操作。因为我认为它不相关,所以我没有在此处包含它。

标签: linux bash shell curly-braces


【解决方案1】:

这不是因为大括号,而是因为管道。

当您将命令与command | tee 之类的管道结合使用时,管道的每一侧都在单独的子进程中执行。因此,Shell 命令在子 shell 中执行。这就是您检测到的这个子外壳。

PS:避免使用ps | grep -v grep 之类的结构,改用pidofpgrep

【讨论】:

  • 感谢您的澄清。我猜想有子外壳的恶作剧,因为 PIDS 因 pipped 命令的数量而异。对我来说,您使用pidofpgrep 的建议是可以接受的。此外,我认为只需将 2 个变量 MYPIDMYOTHERPROCESSES 移到花括号外并将它们与其余变量捆绑在一起就足够了。
  • @martin 花括号内的代码在子shell中执行。无论您对变量所做的任何更改,都不会在大括号之外可见。要在当前 shell 中执行大括号内的代码,请将 | tee -a $LOGFILE 2>&1 更改为 > >(tee -a $LOGFILE) 2>&1(顺便说一句,2>&1 应该放在代码中的管道之前)
  • 2>&1 位上你是正确的 - 这就是我的原始脚本是我在上述提交中的错误。花括号内的脚本的其余部分只不过是使用先前声明的变量测试不同的条件。因此,我很高兴测试在单独的外壳中。但是,我将在大括号内外分别重新测试每个块,以确保获得预期的结果。感谢您的时间和帮助。
猜你喜欢
  • 1970-01-01
  • 2017-12-29
  • 2019-11-26
  • 1970-01-01
  • 1970-01-01
  • 2019-04-01
  • 1970-01-01
  • 2022-08-15
  • 2017-08-10
相关资源
最近更新 更多