【问题标题】:Why does ksh fail to capture standard error during nested command substitutions?为什么 ksh 在嵌套命令替换期间无法捕获标准错误?
【发布时间】:2016-08-26 05:00:01
【问题描述】:

我有以下 shell 脚本。

$ cat foo.sh 
foo()
{
    A=$(uname)
    printf "hello "
    bogus
}

echo output: "$(foo 2>&1)"

它在 bash、zsh、dash 和 posh 中生成以下输出。这是有道理的,因为系统上没有这样的命令bogus

$ bash foo.sh
output: hello foo.sh: line 5: bogus: command not found
$ zsh foo.sh
output: hello foo:4: command not found: bogus
$ dash foo.sh
output: hello foo.sh: 5: foo.sh: bogus: not found
$ posh foo.sh
output: hello foo.sh:8: bogus: not found

但在 Debian 上的 ksh 中,由于调用了 bogus 命令,它不会打印错误消息。

$ ksh foo.sh
output: hello 

出了什么问题?

如果您想了解系统详细信息和 shell 的版本详细信息,请查看以下输出。

$ uname -a
Linux debian1 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt20-1+deb8u2 (2016-01-02) x86_64 GNU/Linux
$ cat /etc/debian_version 
8.3
$ ksh --version
  version         sh (AT&T Research) 93u+ 2012-08-01
$ dpkg -l bash zsh dash posh ksh | tail -n 5
ii  bash           4.3-11+b1      amd64        GNU Bourne Again SHell
ii  dash           0.5.7-4+b1     amd64        POSIX-compliant shell
ii  ksh            93u+20120801-1 amd64        Real, AT&T version of the Korn shell
ii  posh           0.12.3         amd64        Policy-compliant Ordinary SHell
ii  zsh            5.0.7-5        amd64        shell with lots of features

在 CentOS 系统上,我看到了预期的输出。

$ cat /etc/centos-release 
CentOS release 6.7 (Final)
$ ksh --version
  version         sh (AT&T Research) 93u+ 2012-08-01
$ ksh foo.sh
output: hello foo.sh[5]: bogus: not found [No such file or directory]

如果我删除函数 foo 中的命令替换,那么所有 shell 在 Debian 上都会产生类似的输出。

$ cat bar.sh
foo()
{
    printf "hello "
    bogus
}

echo output: "$(foo 2>&1)"
$ bash bar.sh
output: hello bar.sh: line 4: bogus: command not found
$ zsh bar.sh
output: hello foo:3: command not found: bogus
$ dash bar.sh
output: hello bar.sh: 4: bar.sh: bogus: not found
$ posh bar.sh
output: hello bar.sh:7: bogus: not found
$ ksh bar.sh
output: hello bar.sh[4]: bogus: not found [No such file or directory]

为什么ksh 在Debian 上的第一个示例中不打印由于bogus 命令而导致的错误,但在CentOS 上却产生了它?

我在POSIX.1-2008 标准中发现了以下文字:

使用 $(command) 形式,开号后面的所有字符 匹配右括号的括号构成 命令。任何有效的 shell 脚本都可以用于命令,除了 仅由产生未指定的重定向组成的脚本 结果

我怀疑我以粗体突出显示的文本部分是导致上述示例中未指定行为的原因。但是,我并不完全确定,因为我在标准中找不到“仅包含重定向的脚本”的定义。

我有两个问题。

  1. 我们能否通过充分参考标准或人来证明 第一个示例中ksh 的输出是否是错误或 不是吗?
  2. 我还能如何捕获由 shell 编写的标准错误 shell函数正在执行命令的函数 替换?

【问题讨论】:

  • 我看不出加粗的部分是如何相关的。那是在谈论像 $(<filename) 这样的东西,你的脚本中没有。
  • 我猜这是一个 ksh 错误。

标签: linux shell posix ksh io-redirection


【解决方案1】:

我搜索了这个问题,发现如下:

根据标准,这是一个错误,因为每当找不到命令时,都会给出“找不到命令”错误。

这是一个已在 ksh 的 beta 分支中解决的错误。使用那个分支。我在 ubuntu 中对其进行了测试,它对我有用。

我是这样做的:

git clone https://github.com/att/ast.git
cd ast
git checkout beta
bin/package make
cp arch/linux.i386-64/bin/ksh /usr/local/bin/ksh

master 分支的 ksh 有很多 bug。只需检查https://github.com/att/ast/commits/beta 中的提交日志即可。

【讨论】:

  • 您的命令顺序不一致——您克隆ast,然后cd 到ast-open,我认为最后一行应该是安装或复制命令?
  • 谢谢,我修好了。早些时候,该回购曾经被称为 ast-open。最后是复制,以便您可以从任何路径使用 ksh
  • 感谢您花时间编译 ksh 的 beta 版本并测试此问题。我也可以按照您的步骤进行验证。使用 ksh 的 beta 版本,ast/arch/linux.i386-64/bin/ksh --version 输出 version sh (AT&T Research) 93v- 2014-12-24ast/arch/linux.i386-64/bin/ksh foo.sh 输出 output: hello foo.sh[5]: bogus: not found [No such file or directory]
  • 是的,centos 中的版本保持不变,因为他们正在应用自己的补丁,其中一个解决了这个问题。检查更新日志:rpmfind.net/linux/RPM/centos/updates/6.7/x86_64/Packages/…
猜你喜欢
  • 2015-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-25
  • 2013-07-08
  • 2016-09-28
  • 1970-01-01
相关资源
最近更新 更多