0

I am running this bash command:

xe pbd-unplug uuid=$PBDUUID

If the result exists - i.e. if the variable PBDUUID is not empty then I would like to run another command:

xe sr-forget uuid=$SRUUID

However, if the variable is blank then I would like print an error message

Error: No PBD.

and for the script to exit immediately (similar to sys.exit() in Python).

Is there a way to combine this if else then into one line? Also, what is the bash equivalent of sys.exit()?

Additional Information/Comment:

Regarding comment by Dilettant, yes that approach (if [ -z ${PBDUUID} ]; then) will also work. I was not aware of it. Thanks for this. That seems quite intuitive.

edesz
  • 8,579
  • 17
  • 58
  • 103
  • Apologies if this is a repeat question. If so, please let me know. – edesz Jul 04 '16 at 20:55
  • 1
    What is wrong with `if [ -z ${PBDUUID} ]; then printf "foo"; else printf "bar"; fi` - please amend to the question. Thanks. – Dilettant Jul 04 '16 at 21:00
  • 2
    "In one line"? Why? One-liners are generally less readable or, if short-circuiting boolean logic is used to construct them, more buggy than equivalent code using less terse constructs. – Charles Duffy Jul 04 '16 at 21:01
  • BTW, defining all-uppercase names for your own shell variables is bad form. All-uppercase variable names are used for variables with meaning to the shell or system, whereas the namespace with at least one-lowercase character is reserved for application use. See http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html, fourth paragraph, keeping in mind that environment variables and shell variables share a single namespace. (That is to say: If you create a shell variable whose name overlaps an environment variable, the environment variable will automatically be overwritten). – Charles Duffy Jul 04 '16 at 21:04
  • @Dilettant, plenty's wrong with that: It's not quoting adequately. `[ -z "$PBDUUID" ]` would be a correct formulation. Keep in mind that `[ -z ]` tests whether the string `"-z"` is non-empty, and thus returns true. – Charles Duffy Jul 04 '16 at 21:08
  • 1
    @Dilettant, ...alternately, in bash or another shell adopting ksh extensions, you could use `[[ -z $PBDUUID ]]` instead, which suppresses field-splitting. – Charles Duffy Jul 04 '16 at 21:11
  • @CharlesDuffy all righty, here in Europe it is late, and in the US you guys are awake, so take over for now, and trusting the ongoing edits of your answer, I will keep the +1 ... ;-) – Dilettant Jul 04 '16 at 21:12
  • @CharlesDuffy: I'm in not sure how useful your warning is. POSIX says: _Environment variable names used by the utilities in the Shell and Utilities volume of IEEE Std 1003.1-2008 consist solely of uppercase letters, digits, and the `` ('`_`') from the characters defined in Portable Character Set and do not begin with a digit. … The name space of environment variable names containing lowercase letters is reserved for applications. Applications can define any environment variables with names from this name space without modifying the behavior of the standard utilities._ […continued…] – Jonathan Leffler Jul 04 '16 at 21:17
  • […continuation…] You're right that there is a chance that a utility (command) will use a particular environment variable name in all upper-case, but the chances of it being a real problem are minuscule and fly in the face of long-standing tradition. If a new application wants to be absolutely sure that its own environment variables won't affect POSIX utilities by accident, it should use one or more lower-case letters in the name. Many, many, many existing applications use upper-case letters, and they've survived for years without running into problems. […continued…] – Jonathan Leffler Jul 04 '16 at 21:17
  • […continuation…] Personally, I'm going to take an informed decision to ignore the issue, aware that there could, in theory — but not in practice — be a problem. – Jonathan Leffler Jul 04 '16 at 21:18
  • I wasn't aware of the uppercase issue. Sorry about that. Why do they use uppercase here: http://serverfault.com/questions/103359/how-to-create-a-uuid-in-bash – edesz Jul 04 '16 at 21:25
  • @WR, eh? The accepted answer uses `uuid=$(uuidgen)`, which... well... *doesn't* use upper-case. That said, there are lots of folks doing things because that's the way they've always done them, or that's the way they saw them being done when reading other peoples' code. And then you had the folks coming from pre-UNIX mainframe operating systems where upper-case variable names *were* in fact required, so you had a lot of folks back in the early days of UNIX who were following pre-UNIX conventions. Couple that with decades of cargo-cult programmers copying what they'd seen and you get to today. – Charles Duffy Jul 04 '16 at 21:30
  • @JonathanLeffler, I disagree that it's "miniscule". How many problems have you seen here on SO caused by folks using `PATH` for their own variables, rather than `path`? – Charles Duffy Jul 04 '16 at 21:31
  • @JonathanLeffler, ...granted, the gotchas (like that one) with guaranteed impact get caught in debugging, but if folks Did The Right Thing in the first place they'd avoid the guaranteed cases as well as the improbable ones. – Charles Duffy Jul 04 '16 at 21:33
  • @CharlesDuffy: I've not noticed any questions where people set PATH unaware of what it did, but I've not seen every shell question on SO (nor do I have plans to go check). It's the usual game — you need to know the names defined by POSIX (and avoid using them except for the purpose defined by POSIX), and you need to be aware of what your utilities use. As you're undoubtedly aware, you could still run into conflicts between utilities if two different utilities both decide to use an environment variable `$alt_browser` for two different tasks — just as much as if they used `$ALT_BROWSER`. – Jonathan Leffler Jul 04 '16 at 21:55
  • 1
    @CharlesDuffy: we don't need to prolong this discussion. I've raised my concerns once, which is enough. We can let people make their own minds up. (Incidentally, you might prefer to update your link from the 2001 POSIX specification to the 2008/2013 version — http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html — for future reference. I used it in my quote; the wording is marginally different, but the intent is the same.) – Jonathan Leffler Jul 04 '16 at 21:58
  • @JonathanLeffler, ...there's more than just POSIX, there are also shell builtins and variables defined by OS-bundled tools. `for HOSTNAME in ...` or `for USER in...` doesn't exactly seem improbable, but if it confuses code that runs in the same shell but expects `HOSTNAME` or `USER` to have its value defined by the shell or (if on an OS that does so) exported by PAM modules or similar, that's a needless source of surprises. Anyhow, if you *were* interested in continuing the discussion I could find plenty of SO questions re: the `path` / `PATH` conflict -- but indeed, we've stated our cases. – Charles Duffy Jul 04 '16 at 23:55

1 Answers1

3
if xe pbd-unplug uuid="$PBDUUID"; then xe sr-forget "uuid=$SRUUID"; else echo "Error: No PBD."; exit 1; fi

More readably, that is:

if xe pbd-unplug uuid="$PBDUUID"; then
  xe sr-forget "uuid=$SRUUID"
else
  echo "Error: No PBD." >&2
  exit 1
fi

BTW, if your goal is to check whether a variable is blank, that would look more like the following:

if [ -z "$PDBUUID" ]; then
  xe pdb-unplug uuid="$PDBUUID" && xe sr-forget "uuid=$SRUUID"
else
  echo "Error: No PBD." >&2
  exit 1
fi

If exit doesn't do as you intend, then this code is presumably running in a subshell, and thus exit is exiting that subshell rather than your script as a whole. See SubShell or the "Actions that Create a Subshell" section of the processtree bash-hackers.org page.

Charles Duffy
  • 235,655
  • 34
  • 305
  • 356