“set -e -o pipefail” 在 Ubuntu 16 上的 bash 脚本中不起作用

“set -e -o pipefail” 在 Ubuntu 16 上的 bash 脚本中不起作用

我一直在尝试在 Ubuntu 16 上运行我在 CentOS 7 上开发的 bash 脚本。

脚本的第一行是:

set -o nounset -o pipefail -o errexit

当我尝试运行该脚本时,出现以下错误:

project.sh: 6: set: Illegal option -o pipefail

如何解决这个问题?我也在回答这个问题但它没有帮助(我的文件不是make)。

答案1

在 Ubuntu 上,默认 shell 是dash(又名 Debian Almquist Shell),它/bin/sh是符号链接。当您的 shell 脚本使用 运行时#!/bin/sh,您实际上是在尝试使用默认 shell 运行它。但是,dash没有选项pipefail,这就是您收到错误的原因。

# Verifying what /bin/sh is symlinked to dash
$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 2月  17  2016 /bin/sh -> dash
# Verify that pipefail doesn't exist as option for dash
$ dash    
$ set -o | grep pipefail                                              
$ set -o pipefail
dash: 1: set: Illegal option -o pipefail
$ sh
$ set -o pipefail
sh: 1: set: Illegal option -o pipefail
# Try this same option in bash
$ bash --posix
bash-4.3$ set -o pipefail
bash-4.3$  
# no error

答案2

对于那些寻找一个可以绕过dashUbuntu 问题的简单脚本的人来说,你可以使用

bash | set +o pipefail

答案3

还有一个可能导致此(或类似)问题的选项:脚本文件中的 Windows 行结尾(CRLF,“\r\n”)。

在 WSL 上发生这种情况的可能性比在原始 Ubuntu 上发生的可能性大得多,但我花了一段时间才发现。

由于行尾错误,解释器将最后一个参数准确读取为pipefail\r,这被解释为未知参数。但\r在终端中不可见,这使得很难理解原因。

解决方法是确保文本编辑器中的行尾设置为 LF。

答案4

尝试使用下面的标志,然后它就可以工作了。我已经验证过了。

#!/bin/bash
set -e -o pipefail

# to reset use
# set +e +o pipefail

相关内容