在 shell 命令(不是脚本)中获得“确保”/“最终”功能?

Ian*_*Ian 7 command-line bash exit exit-status

我需要知道命令是成功还是失败,然后无条件地运行一些清理。

用于执行顺序命令的正常选项似乎都不适用于此处:

$ mycmd.sh && rm -rf temp_files/    # correct exit status, cleanup fails if mycmd fails
$ mycmd.sh ;  rm -rf temp_files/  # incorrect exit status, always cleans up
$ mycmd.sh || rm -rf temp_files/    # correct exit status, cleanup fails if mycmd succeeds
Run Code Online (Sandbox Code Playgroud)

如果我要在 shell 脚本中执行此操作,我会执行以下操作:

#!/usr/bin/env bash
mycmd.sh
RET=$?
rm -rf temp_files
exit $RET
Run Code Online (Sandbox Code Playgroud)

有没有比分号将所有这些命令链接在一起更惯用的方法来在命令行上完成它?

PSk*_*cik 13

脚本中的换行符几乎总是等价于分号:

mycmd.sh; ret=$?; rm -rf temp_files; exit $ret
Run Code Online (Sandbox Code Playgroud)

回应编辑:

或者,您也可以使用 atrap和一个子shell:

( trap 'rm -rf temp_files' EXIT; mycmd.sh )
Run Code Online (Sandbox Code Playgroud)


cat*_*cat 8

如果您正在寻找某些语言的副本try { } finally { },还有另一种方法:使用trap内置bash和其他 POSIXy shell(请参阅 参考资料help trap)。

#!/bin/bash

# exit with this by default, if it is not set later
exit_code=0  

# the cleanup function will be the exit point
cleanup () {
  # ignore stderr from rm incase the hook is called twice
  rm -rf "temp_files/" &> /dev/null  
  # exit(code)
  exit $exit_code
}

# register the cleanup function for all these signal types (see link below)
trap cleanup EXIT ERR INT TERM

# run your other script
mycmd.sh

# set the exit_code with the real result, used when cleanup is called
exit_code=$?
Run Code Online (Sandbox Code Playgroud)

阅读有关 trap 命令的参数的信息。

请注意,它cleanup被称为:

  • 如果此脚本发送 SIGINT 或 SIGTERM 或按下 CTRL-C (SIGINT)
  • 如果此脚本以 0 正常退出
  • 如果 mycmd.sh 以非零状态退出(可能不是您想要的——从陷阱的参数中删除ERR以禁用

  • 请注意,“cleanup”将在“CTRL-C”上运行两次。可以通过从信号中删除“EXIT”并在“mycmd.sh”之后显式调用“cleanup”来避免这种情况。 (2认同)