gpt4 book ai didi

linux - 如何使 bash 中的 RETURN 陷阱保留返回码?

转载 作者:IT王子 更新时间:2023-10-29 00:52:50 29 4
gpt4 key购买 nike

下面是我正在编写的脚本的简化方案。程序必须以不同的方式获取参数,因此对几个函数进行了精细划分。

问题是从深层函数返回值的链式加载在陷阱处中断,在陷阱处检查结果以显示消息。

#! /usr/bin/env bash

check_a_param() {
[ "$1" = return_ok ] && return 0 || return 3
}

check_params() {
# This trap should catch negative results from the functions
# performing actual checks, like check_a_param() below.
return_trap() {
local retval=$?
[ $retval -ne 0 ] && echo 'Bad, bad… Dropping to manual setup.'
return $retval
}
# check_params can be called from different functions, not only
# setup(). But the other functions don’t care about the return value
# of check_params().
[ "${FUNCNAME[1]}" = setup ] \
&& trap "return_trap; got_retval=$?; trap - RETURN; return $got_retval;" RETURN
check_a_param 'return_bad' || return $?
# …
# Here we check another parameters in the same way.
# …
echo 'Provided parameters are valid.'
return 0 # To be sure.
}

ask_for_params() {
echo 'User sets params manually step by step.'
}

setup() {
[ "$1" = force_manual ] && local MANUAL=t
# If gathered parameters do not pass check_params()
# the script shall resort to asking user for entering them.
[ ! -v MANUAL ] && {
check_params \
&& echo "check_params() returned with 0. Not running manual setup."
|| false
}|| ask_for_params
# do_the_job
}

setup "$@" # Either empty or ‘force_manual’.

它应该如何工作:

              ↗ 3 → 3→ trap →3                     ↗ || ask_for_params ↘
check_a_param >>> check_params >>> [ ! -v MANUAL ] ↓
↘ 0 → 0→ trap →0 ↘ && ____________ do_the_job

想法是,如果检查失败,它的返回码强制check_params()也返回,这反过来又会触发 || ask_for_params条件 setup() .但是陷阱返回 0:

              ↗ 3 → 3→ trap →0
check_a_param >>> check_params >>> [ ! -v MANUAL ] &&… >>> do_the_job
↘ 0 → 0→ trap →0

如果您尝试按原样运行脚本,您应该会看到

Bad, bad… Dropping to manual setup.
check_params() returned with 0. Not running manual setup.

这意味着错误的结果触发了陷阱(!)但是设置它的母函数没有传递结果。

试图设置一个 hack 我已经尝试过

  • 将retval设置为全局变量declare -g retval=$?return_trap()并在设置陷阱的行中使用它的值。变量已设置([ -v retval ] 成功返回),但是……没有值。有趣。
  • 好吧,我们输入retval=Eehcheck_params() , 在 return_trap() 之外并将其设置为 $?作为通常的参数。不,retval在函数中没有设置全局变量的值,它保持为“Eeh”。不,没有 local指示。默认情况下,它应该被视为全局的。如果你把 test=1check_params()test=3check_a_param()然后用 echo $test 打印出来在 setup() 的末尾,你应该看到 3。至少我看到了。 declare -g正如预期的那样,这里没有任何区别。
  • 也许这就是职能范围?不,那也不是。搬家return_trap()连同 declare -g retval=Eeh没有任何区别。
  • 当现代软件走向衰落时,是时候诉诸于旧的写入文件的方式了。让我们使用 retval=$?; echo $retval >/tmp/t 将 retval 打印到/tmp/t在 return_trap()并用

    读回

    trap "return_trap; trap - RETURN; return $(</tmp/t)" RETURN

现在我们终于可以看到最后一个从文件中读取数字的 return 指令实际上返回了 3。但是 check_params()仍然返回 0!

++ trap - RETURN
++ return 3
+ retval2=0
+ echo 'check_params() returned with 0. Not running manual setup.'
check_params() returned with 0. Not running manual setup.

如果参数为 trap command 严格来说是一个函数名,它返回原始结果。原来一个,不是什么return_trap()返回。我试图增加结果,但仍然得到 3。您可能还会问“为什么您需要如此频繁地解除陷阱?”。这是为了避免另一个错误,该错误导致陷阱每次都触发,即使是 check_params() 时也是如此。从另一个函数调用。 RETURN 上的陷阱是本地事物,它们不会被其他函数继承,除非在它们上明确设置了调试或跟踪标志,但看起来它们在运行之间保留了陷阱设置。或者 bash 为他们设置陷阱。仅当从特定函数调用 check_params() 时才应设置此陷阱,但如果未取消设置陷阱,则每次都会继续触发 check_a_param()返回一个大于零的值,与 FUNCNAME[1] 中的内容无关.

在这里我放弃了,因为我现在看到的唯一导出是在每个|| return $?之前对调用函数实现检查。在 check_params() .但它太丑了,伤了我的眼睛。

我只能补充一点,$?在设置陷阱的行中,将始终返回 0。 因此,例如,如果您声明一个 local变量 retvalreturn_trap() , 并放入这样的代码来检查它

trap "return_trap; [ -v retval ]; echo $?; trap - RETURN; return $retval" RETURN

无论retval 是否存在,它都会打印 0实际上是设置还是不设置,但是如果你使用

trap "return_trap; [ -v retval ] && echo set || echo unset; trap - RETURN; return $retval" RETURN

它将打印‘unset’。


GNU bash,版本 4.3.39(1)-release (x86_64-pc-linux-gnu)

最佳答案

很有趣,

trap "return_trap; trap - RETURN" RETURN

简单有效。

[ ! -v MANUAL ] && {
check_params; retval2=$?
[ $retval2 -eq 0 ] \
&& echo "check_params() returned with 0. Not running manual setup." \
|| false
}|| ask_for_params

这是踪迹。

+ check_a_parameter return_bad
+ '[' return_bad = return_ok ']'
+ return 3
+ return 3
++ return_trap
++ local retval=3
++ echo 3
++ '[' 3 -ne 0 ']'
++ echo 'Bad, bad… Dropping to manual setup.'
Bad, bad… Dropping to manual setup.
++ return 3
++ trap - RETURN
+ retval2=3
+ '[' 3 -eq 0 ']'
+ false
+ ask_for_params
+ echo 'User sets params manually step by step.'
User sets params manually step by step.

所以答案很简单:不要尝试覆盖传递给 trap 命令的行中的结果。 Bash 为您处理一切。

关于linux - 如何使 bash 中的 RETURN 陷阱保留返回码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36442572/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com