4

I'd like to write the following test in an installer script1:

if [ -n "`/etc/grub.d/30_os-prober`" ]; then
    install_dual_boot
else
    install_linux_only
fi

However, it's also possible that 30_os-prober produces no output because it somehow failed to complete. If 30_os-prober fails with a non-zero exit status, it would be safer to assume the a dual-boot situation.

How can I check that 30_os-prober produced no output successfully?

Basically, I would like to obtain an effect similar to…

if [ -n "`/etc/grub.d/30_os-prober`" ]; then
    # Do stuff for a dual-boot machine
    install_dual_boot
elif ! /etc/grub.d/30_os-prober >/dev/null; then
    # OS probe failed; assume dual boot out of abundance of caution
    install_dual_boot
else
    install_linux_only
fi

… but without running the same command twice.


1 Background information: 30_os-prober comes with GRUB2, and the script I am writing is part of my custom configuration for FAI.

200_success
  • 5,535

2 Answers2

10

First of all, while they are functionally equivalent, $(…) is widely considered to be clearer than `…` — see this, this, and this.  Secondly, you don’t need to use $? to check whether a command succeeded or failed.  My attention was recently drawn to Section 2.9.1, Simple Commands of The Open Group Base Specifications for Shell & Utilities (Issue 7):

A "simple command" is a sequence of optional variable assignments and redirections, in any sequence, optionally followed by words and redirections, terminated by a control operator.

When a given simple command is required to be executed …
                          ⋮                                                                                (blah, blah, blah …)

If there is a command name, execution shall continue as described in Command Search and Execution.  If there is no command name, but the command contained a command substitution, the command shall complete with the exit status of the last command substitution performed.  …

For example,

  • the exit status of the command

    ls -ld "module_$(uname).c"
    

    is the exit status from the ls, but

  • the exit status of the command

    myfile="module_$(uname).c"
    

    is the exit status from the uname.

So ferada’s answer can be streamlined a bit:

if output=$(/etc/grub.d/30_os-prober)  &&  [ -z "$output" ]
    # i.e., if 30_os-prober successfully produced no output
then
    install_linux_only
else
    install_dual_boot
fi

Note that it is good practice to use all-upper-case names only for environment variables (or variables to be visible throughout the script).  Variables of limited scope are usually named in lower case (or, if you prefer, camelCase).

6

You can assign the value to a variable and then check the exit status as well:

PROBE_VALUE=`/etc/grub.d/30_os-prober`

if [ "$?" -eq 0 ] && [ -z "$PROBE_VALUE" ]; then
    install_linux_only
else
    install_dual_boot
fi
ferada
  • 161