Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Here's a simplified version of my script. My question is, How do I return the exit code from apt-get in this case?

#!/bin/bash
install_auto() {
apt-get -h > /dev/null 2>&1
if [ $? -eq 0 ] ; then
    return $(sudo apt-get install --assume-yes $@)
fi
return 1
}
echo "installing $@"
install_auto "$@"
echo $?
echo "finished"
exit 0

The output is:

./install_test.sh: line 5: return: Reading: numeric argument required

Update: I came up with something that works:

return $(sudo apt-get install --assume-yes "$@" >/dev/null 2>&1; echo $?)

Is that a good approach?

share|improve this question

2 Answers 2

up vote 4 down vote accepted

Bash's return() can only return numerical arguments. In any case, by default, it will return the exit status of the last command run. So, all you really need is:

#!/usr/bin/env bash
install_auto() {
apt-get -h > /dev/null 2>&1
if [ $? -eq 0 ] ; then
    sudo apt-get install --assume-yes $@
fi
}

You don't need to explicitly set a value to be returned since by default a function will return $?. However, that will not work if the first apt command failed and you did not go into the if loop. To make it more robust, use this:

#!/usr/bin/env bash
install_auto() {
apt-get -h > /dev/null 2>&1
ret=$?
if [ $ret -eq 0 ] ; then
    ## If this is executed, the else is ignored and $? will be
    ## returned. Here, $?will be the exit status of this command
    sudo apt-get install --assume-yes $@
else
    ## Else, return the exit value of the first apt-get
    return $ret
fi
}

The general rule is that in order to have a function return the exit status of a particular job and not necessarily the last one it ran, you will need to save the exit status to a variable and return the variable:

function foo() {
    run_a_command arg1 arg2 argN
    ## Save the command's exit status into a variable
    return_value= $?

    [the rest of the function  goes here]
    ## return the variable
    return $return_value
}

EDIT: Actually, as @gniourf_gniourf pointed out in the comments, you could greatly simplify the whole thing using &&:

install_auto() {
  apt-get -h > /dev/null 2>&1 &&
  sudo apt-get install --assume-yes $@
}

The return value of this function will be one of:

  1. If apt-get -h failed, it will return its exit code
  2. If apt-get -h succeeded, it will return the exit code of sudo apt-get install.
share|improve this answer
    
Sorry, my example was not clear enough. I need a return statement (or some equivalent logic) in my actual script so stuff following this statement is not executed if apt-get was present on this system. If apt-get is not present, it looks for zypper, etc. I guess adding return $? on the next line of your example after sudo apt-get ... might be sufficient. Is that right? Thanks –  MountainX Jul 7 '13 at 19:12
    
@MountainX see updated answer. The way you have written it (and the way I have written my example) if the apt fails, then its exit status is returned and the function exits, returning the exit value of the at-get. Isn't that what you need? –  terdon Jul 7 '13 at 19:15
2  
the ret variable is useless. apt-get -h > /dev/null 2>&1 && sudo apt-get install --assume-yes "$@" would do the same. Oh, and use more quotes, especially for $@ –  gniourf_gniourf Jul 7 '13 at 19:17
    
@gniourf_gniourf yes indeed, answer updated. –  terdon Jul 7 '13 at 19:22
    
Thanks for the feedback. I pasted my complete function as I realized that my simplified example wasn't enough. I appreciate any further comments. –  MountainX Jul 7 '13 at 19:34

For completeness, here is my actual function with some modifications as suggested by @terdon and @gniourf_gniourf :

install_auto() {
    if [ ! $# -gt 0 ] ; then
        echo "usage: $0 package_name [package_name ...]"
    fi 

    apt-get -h > /dev/null 2>&1
    if [ $? -eq 0 ] ; then
        if [ -f "$@" ] || [[ "$@" =~ '/' ]] ; then
            sudo gdebi -n "$@"
            return $?
        else    
            sudo apt-get install --assume-yes "$@"
            return $?
        fi
    fi

    zypper help > /dev/null 2>&1
    if [ $? -eq 0 ] ; then
            sudo zypper --non-interactive --no-gpg-checks --quiet install --auto-agree-with-licenses "$@"
            return $?
    fi

    #may check other package managers in the future

    echo "ERROR: package manager not found"
    return 255
}

I appreciate any further suggestions.

share|improve this answer
    
The cmd; if [ $? -eq 0 ]; then ... construct is generally better expressed as if cmd; then ... or even just cmd && ... if the "then" part is just a simple command. –  tripleee Jul 8 '13 at 6:00

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.