0

I'm trying to return a value from a function in bash using what I've seen here. But for some reason my script just hangs instead of returning a value from the function. What am I doing wrong (running on Ubuntu)?

#!/bin/bash
...

function check_ftp_file_exists {
  local ftp_path=$1

  echo "Checking whether remote path $ftp_path exists on FTP server $FTP_HOST..."
  echo "ls $1" | sftp -b - -i $FTP_PEM_FILE ${FTP_USER}@${FTP_HOST}
  echo "$?"
}

retval=$(check_ftp_file_exists $FILE_PATH)
echo "here retval is $retval"      # never get here

-- update -- In the above, there seems to be an error with the SFTP command, even though I've lifted it from another script where it works correctly.

THe bigger problem for now though is that using '$()' seems to return anything that I echo inside a function, instead of just the return code of running the external command which is what I want.

E.g.

function exit_on_error {
  local return_code=$1
  local error_message=$2

  if [[ $return_code -ne 0 ]]; then
    echo "$error_message"
    exit $return_code
  fi
}

function get_s3_file {
  local s3_path=$1
  local local_path=$2

  echo "Downloading $s3_path to $local_path..."
  $(aws s3 cp $s3_path $local_path)
  echo "$?"
}

if [[ ! -e "$FTP_PEM_FILE" ]]; then
  exit_on_error $(get_s3_file $S3_PEM_PATH "/tmp/") "Failed to retrieve pem file "
fi

Running the above gives the following debug output:

+ exit_on_error 'Failed to retrieve pem file '
+ local 'return_code=Failed to retrieve pem file '

How can I return only the value of $? after running an external command, to the caller?

7
  • What does happen? Does sftp connect? Does the ls happen? What process is still running when it hangs? Commented Dec 8, 2014 at 15:29
  • Nothing gets printed out. This happens with other functions as well, so I doubt it's anything to do with the sftp command. The whole script just hangs upon entering the function (if it even enters it at all). Commented Dec 8, 2014 at 15:32
  • Add set -x to the very top of the script and see where it actually hangs. If you aren't sure this is where it hangs then you shouldn't have cropped the rest of the script. Commented Dec 8, 2014 at 15:33
  • Put set -xv right before that sftp line, and set +xv right after it. What prints out? Have you tried piping a command to sftp before? Commented Dec 8, 2014 at 15:43
  • As an aside, it would make more sense to return $? but that's what functions do by default anyway, so you could leave it out entirely. Commented Dec 8, 2014 at 15:52

1 Answer 1

1

That's what $() does, it expands to the output produced by the command/function. If you want return code, you just read $? after calling the command/function, e.g.:

OUTPUT=$(grep "root" /etc/passwd)
RETCODE=$?
echo "output: ${OUTPUT}"
echo "retcode: ${RETCODE}"

OUTPUT=$(grep "blablabla" /etc/passwd)
RETCODE=$?
echo "output: ${OUTPUT}"
echo "retcode: ${RETCODE}"

func1()
{
    grep "root" /etc/passwd
}

func2()
{
    grep "blablabla" /etc/passwd
}

OUTPUT=$(func1)
RETCODE=$?
echo "output: ${OUTPUT}"
echo "retcode: ${RETCODE}"

OUTPUT=$(func2)
RETCODE=$?
echo "output: ${OUTPUT}"
echo "retcode: ${RETCODE}"

If, inside the function, you'd like to do something more after calling the command and before returning it's return code, you have to remember the return code in a variable and then use return statement at the end of the function, e.g:

func3()
{
    grep "root" /etc/passwd
    local RETCODE=$?
    # ...
    echo "The End"
    return ${RETCODE}
}

func4()
{
    grep "blablabla" /etc/passwd
    local RETCODE=$?
    # ...
    echo "The End"
    return ${RETCODE}
}

OUTPUT=$(func3)
RETCODE=$?
echo "output: ${OUTPUT}"
echo "retcode: ${RETCODE}"

OUTPUT=$(func4)
RETCODE=$?
echo "output: ${OUTPUT}"
echo "retcode: ${RETCODE}"
Sign up to request clarification or add additional context in comments.

2 Comments

Note name() is a non-portable bash function declaration. The more portable declaration is function name. Bash got a whole lot right, but there are several areas it introduced questionable syntax.
Not according to Greg's Wiki, bash-hackers.org or Ubuntu wiki, which say that function is not defined by POSIX and recommend using name().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.