Rue Vitale
Rue Vitale

Reputation: 1891

Writing successful bash scripts

I have the following bash script

aws s3 sync s3://test/ s3://test-li/

if [[ ! $? -eq 0 ]]; then
   echo "Unable to copy from test bucket"
   exit 1
fi

Is that the right way to run a command and check its return value?

Upvotes: 1

Views: 281

Answers (4)

cdarke
cdarke

Reputation: 44354

Unlike most other languages, in shells like bash the if statement is followed by a command, the brackets are fooling you. [[ is actually a shell keyword (as is !), a development of [ which is a shell built-in, also known as the test command.

Use [[ when you wish to do pattern matching, use (( when you wish to do arithmetic comparisons.

if (( some_variable > 0 ))
then
    ...
fi

If you just want to test if a command worked (returned zero) then any form of brackets are superfluous.

if ! aws s3 sync s3://test/ s3://test-li/
then
    # Always send error messages to stderr
    echo "Unable to copy from test bucket" >&2
    exit 1
fi

Having said that, there are thousands of scripts out there in the wild that do what you have done, and they still work. Unfortunately.

Upvotes: 3

Jokester
Jokester

Reputation: 5617

bash's set -e is quite useful in these cases.

#!/bin/bash
set -e
aws s3 sync s3://test/ s3://test-li/
# if `aws` returns non-zero, the following code will not be executed

echo 'it succeeded!'

Upvotes: 0

Barmar
Barmar

Reputation: 780851

Your way will work. A simpler way is to put the command directly in the if:

if ! aws s3 sync s3://test/ s3://test-li/
then
    echo "Unable to copy from test bucket"
    exit 1
fi

Upvotes: 1

shellter
shellter

Reputation: 37258

Your code will work, but any good shell script declares what shell should interpret it. You should add a first line of your script (no spaces at the left margin)

#!/bin/bash

(Or whatever is the correct path to bash in your environment). 99% that it is /bin/bash.

Your test is a slightly baroque, there is an -ne operator that you could use, i.e.

if [[ $? -ne 0 ]] ; then 
   . . .

Or you can go advanced, and let if directly test the return code from you aws command, i.e.

if ! aws sync s3://test/ s3://test-li/ ; then
  echo "Unable to copy from test bucket"
   exit 1
fi

In this case, you need the ! to have block execute.

You could even capture any output so you can review error msgs etc with

if ! aws sync s3://test/ s3://test-li/ > /tmp/aws_launchlog.txt 2>&1 ; then
  echo "Unable to copy from test bucket"
   exit 1
fi

IHTH

Upvotes: 4

Related Questions