【问题标题】:Syntax error in shell script with process substitution带有进程替换的 shell 脚本中的语法错误
【发布时间】:2012-08-20 16:17:38
【问题描述】:

我有一个用来备份我的系统的 shell 脚本。有一行:

tar -Pzcpf /backups/backup.tar.gz --directory=/ --exclude=proc --exclude=sys --exclude=dev/pts --exclude=backups --exclude=var/log / 2> >(grep -v 'socket ignored' >&2)

如您所见,我一直在尝试使用 this blog post 过滤掉 tar 中恼人的、无用的“socket被忽略”错误。

执行时我从 shell 得到的是:

/bin/sysback:第 45 行:意外标记附近的语法错误 >' /bin/sysback: line 45:tar -Pzcpf /backups/backup --directory=/ --exclude=proc --exclude=sys --exclude=dev/pts --exclude=backups --exclude=var/log / 2> >(grep -v 'socket被忽略' >&2)'

【问题讨论】:

  • 我认为2> >( 应该是2>(
  • 在此更改后没有给出语法错误,但也没有过滤掉输出。
  • >(...) 进程替换语法是非标准功能,您的 shell 显然不支持它。使用不同的 shell,或者可能是更新版本的 bash。
  • 我的立场是正确的,2> >( 似乎是将 stderr 重定向到子 shell 的方法,并且运行 (echo "FOO";echo "FOO" >&2) 2> >(grep -v FOO >&2) 使用 GNU bash 4.2.24 输出单个“FOO”。你用的是什么外壳?
  • cron 将使用sh 运行您的脚本,在Debian 系统上是dash,而不是bash。在您的脚本中添加!#/bin/bash 可能会有所帮助(但我对cron 并不熟悉,并且没有直接使用Debian 的经验)。

标签: linux bash shell process-substitution


【解决方案1】:

您使用的语法是基本 shell 语法的 bash 扩展,因此您必须小心使用 bash 运行脚本。 (Ksh 也有 >(…) 进程替换,但在重定向后不支持它。Zsh 会很好。)

鉴于您收到的错误消息,您正在 bash 中运行此脚本,但在其 POSIX 兼容模式下,而不是在完整的 bash 模式下。注意使用明确的#!/bin/bash 行来调用您的脚本。 #!/bin/sh 不会这样做,即使 /bin/sh 是 bash 的符号链接,因为如果以名称 sh 调用 bash,它会以 POSIX 模式运行。如果您使用 bash 功能,请始终按名称调用 bash。

如果您想使用 bash 功能,请注意不要设置环境变量 POSIXLY_CORRECT 或在命令行中传递 --posix 选项。

或者,不要使用这种特定于 bash 的语法;使用可移植的构造,例如 Stephane Rouberol 提出的构造。

【讨论】:

    【解决方案2】:

    怎么样:

     tar -Pzcpf /backups/backup.tar.gz --directory=/ \
         --exclude=proc --exclude=sys --exclude=dev/pts \
         --exclude=backups --exclude=var/log 2>&1 | grep -v 'socket ignored'
    

    【讨论】:

    • 即使您在此处提供的解决方案是该解决方案的合法替代方案,我仍将选择@Gilles 解决方案作为正确答案,因为它回答了他提出的问题。不过,谢谢您的回答。
    【解决方案3】:

    我发现,在 gentoo 上,如果 sh 是 /bin/bash 的链接,如果您使用 'sh "scriptname"' 调用脚本,它不会将其作为 bash 脚本运行并失败:

    matchmorethan.sh: line 34: syntax error near unexpected token `<'
    matchmorethan.sh: line 34: `done < <( cat $matchfile )'
    

    因此,如果您需要使用 Process Substitution 功能,您需要专门使用 bash 运行它。但我没有找到任何关于此的参考。

    【讨论】:

      【解决方案4】:

      实际上,当 GNU tar 提供忽略“套接字忽略”警告的选项时,您不必在 std 错误中进行这种重定向。

      tar --warning='no-file-ignored' -Pzcpf /backups/backup.tar.gz --directory=/ --exclude=proc --exclude=sys --exclude=dev/pts --exclude=backups --exclude=var/log / 2> new.err
      

      You could find the original link with more ignore options here

      【讨论】:

      • 感谢您的评论,但特别感谢您的链接:)
      猜你喜欢
      • 2015-11-09
      • 1970-01-01
      • 2013-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-13
      • 2012-09-17
      相关资源
      最近更新 更多