我是在终端中获取 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 并在那里获取源代码。就像是:
打开一个新终端并按照您想要的方式设置一切。你提到了一些环境变量之类的。将它们设置在这里。
在该终端中,启动一个新的 shell。例如,
bash
。做你的事。获取您的脚本。如果它退出,您将被扔到第一个 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,您就可以返回获取脚本。