如何执行命令,如果失败,执行另一个命令并返回1?


3

我习惯了其他语言的这种风格:

do_something || (log_error; return 1) # do something, and if that fails, log the error and then return 1 no matter what, even if the logging fails.

但我似乎无法在bash中找到相同的东西。问题是括号工作类似于具有其自身范围的函数,并且返回1将不具有预期的行为。

这是我到目前为止所做的,但并不完美:

! do_something && log_error && return 1

这个问题就是!令人困惑,返回1取决于日志记录的成功。

这个更好,但更详细:

do_something || (log_error; return 1) || return 1

有什么想法吗?


return 语句只有在脚本或函数内部才有意义 - 而不是在命令行中。你想将1人归还给谁?

@htor你是对的,我总是在一个函数中使用这个片段。因为有时我需要包含脚本,有时我需要将其作为独立脚本执行。
ChocoDeveloper

@ChocoDeveloper:使用 return 从shell函数返回但继续执行调用它的脚本;使用 exit 退出整个shell(即脚本)。除非你在括号中,在这种情况下,你在子shell中 exit 仅退出带括号(subshel​​l)的表达式。
Gordon Davisson

@GordonDavisson是的,问题是我在括号内有脚本的有效负载(外面我只有一些我总是使用的变量和函数),将stdout / stderr(大多数时候我想要两者)重定向到日志文件,然后退出我上次尝试时停止了重定向。这样我就可以让每个脚本处理自己的日志,而不是从调用者那里(例如,来自cli或cron文件)。
ChocoDeveloper

1
@ChocoDeveloper:由于每个脚本(通常)作为单独的shell运行,因此您可以使用例如 exec >output.log 2>error.log 它不会搞乱调用脚本。或者你可以使用 { payload; } >output.log 2>error.log 并且重定向仅适用于括号中的内容,而不需要子shell。
Gordon Davisson

Answers:


4

使用大括号。

 do_something || { log_error; return 1;}

1

最后一个命令运行的退出状态保存在 $? 变量。所以,您可以执行以下操作:

do something
if [[ $? > 0 ]]; then 
   do log_error; exit 1; 
fi

为了便于阅读,我喜欢这样。但是,你的确非常好,你只需要更换 &&;

! do_something && log_error ; return 1

&& 表示“仅在前一个命令成功退出时才执行下一个命令” ; 只是意味着“执行下一个命令”。


在你的第二个例子中, return 1 在成功的情况下执行。
BatchyX

据我所知,它是在成功和失败的情况下执行的。退出状态 ! ls /etc && echo "FAIL" > ~/log ; return 1 和的 ls /etcaaa && echo "FAIL" > ~/log ; return 1 是1。
terdon
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.