采购 Bash 脚本 - 出错时返回,而不是退出?

采购 Bash 脚本 - 出错时返回,而不是退出?

我是在终端中获取 bash 脚本,因此错误退出

set -o errexit

杀死我的终端,这非常烦人,因为我必须关闭终端,打开另一个终端,然后重置一些变量。

到目前为止,使用

command || return

脚本中的线条正在做我想要的事情

set -o errexit

要做...但我希望整个脚本都完成;不仅仅是一行/命令

我有一个充满用于设置站点的命令的文件,但我不想执行命令 ||返回

对于文件中的每一行

是否有另一个设置选项,或者其他什么只会“返回”而不是退出终端?

--只是为了清楚起见,我想终止脚本,并使终端处于与按 ctrl+C 终止终端中运行的服务相同的状态。command || return这样做。但我不想附加|| return到文件中的每一行。所以我正在寻找类似的东西set -o errexit,这不会导致终端关闭

- - 笔记: 创建一个包含两行的哑脚本(super.sh):

create_path=~/Desktop/site_builder/create.sh
source $create_path blah

并放置set -o errexit在create.sh的顶部,

完全按照我的预期工作。然而,必须创建一个包含两行的文件,只是为了调用另一个 bash 脚本,而不是仅仅从终端调用它,这真的很愚蠢。呃呃呃

以下是一些示例:

在 super.sh 中

#!/bin/bash

create_path=~/Desktop/site_builder/create.sh
source $create_path blah

在create.sh中

#!/bin/bash
set -o errexit
#line below this is a line that fails and will cause the script to stop and return to the terminal as expected 
sed "s/@@SITE_NAME@@/$dirname" 
~/Desktop/site_builder/template_files/base.html > ~/Desktop/$dirname/templates/base.html # a line with a stupid error

在终端中:

 $ bash super.sh

输出如预期:

my-mac$

这有效。多么烦人的解决方案啊。

理想情况下,从终端执行愚蠢的 super.sh 文件中的内容,而不是 super.sh 文件 :D,而不需要关闭终端。这就是我正在尝试做的事情所发生的情况:

终端命令:

my-mac$ source $create_path blah

在 create.sh 中我仍然有set -o errexit

这是终端上的输出

    sed: 1: "s/@@SITE_NAME@@/blah": unterminated substitute in regular expression
Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.

[Process completed]

然后终端就被冻结了。 Ctrl+C 不起作用,Ctrl+D 也不起作用

如果不是set -o errexit,如果我只是command || return在 create.sh 文件中的任何地方使用语句,那么我就得到了我想要的,同时直接在终端上执行 superser.sh 中的行(而不是从终端调用 super.sh)。但这也不是一个实际的解决方案。

笔记:我喜欢 @terdon 关于生成子 shell 的答案,所以我最终只是通过脚本而不是终端生成子 shell,正如他( )在整个脚本周围使用大括号在答案中所示。他的答案也有效。

答案1

只需使用故障保护来获取文件:

source the-source-file || true

...那么即使失败,整个命令也不会失败source

答案2

这是唯一适合我需要完成的任务(创建虚拟环境然后激活它,然后从 bash 脚本安装需求):

从脚本生成一个子 shell/子 shell,如下所示:

愚蠢的文件.sh

(
set -o errexit
#bunch of commands
#one line fails
)

使用以下命令运行愚蠢的文件:

source stupid_file.sh <file arguments here> || true

结束。

**鞠躬**

(归功于 Jeff 和 Terdon)

答案3

set -o errexit您可以使用以下代替trap

trap 'trap - ERR RETURN; kill -INT $$ ; return' ERR RETURN

kill -INT $$行为类似于exit,但如果脚本是来源的,它什么都不做(而是运行return)(我相信这是有效的,因为输入提示捕获了信号,阻止了 shell 退出)

trap - ...禁用陷阱,以便它们在脚本退出后不会运行

答案4

作为一个简单的解决方法,您可以在当前 shell 中运行一个 shell 并在那里获取源代码。就像是:

  1. 打开一个新终端并按照您想要的方式设置一切。你提到了一些环境变量之类的。将它们设置在这里。

  2. 在该终端中,启动一个新的 shell。例如,bash

  3. 做你的事。获取您的脚本。如果它退出,您将被扔到第一个 shell 中,并且一切仍处于设置状态。只要再跑bash一次,你就可以恢复正常了。

为了说明这一点,我创建了这个脚本,如果您尝试获取它,该脚本将会失败:

$ cat /home/terdon/scripts/bar.sh
set -o errexit
var='bar

让我们看看如果我启动一个嵌套 shell 会话然后获取它会发生什么(请注意,我使用命令的可移植名称source.;source是一个 bashism):

parent-shell $ bash      ## start a new shell
child-shell $ . ~/scripts/bar.sh
bash: /home/terdon/scripts/bar.sh: line 2: unexpected EOF while looking for matching `''
parent-shell $ 

正如您所看到的,语法错误导致源脚本退出,这又导致我的 shell 会话退出,但由于它是一个嵌套会话,这只是让我回到原始的父 shell,所有变量仍然设置。现在,只需再次运行一个新的 shell,您就可以返回获取脚本。

相关内容