Why can't I capture AWS EC2 CLI Output in Bash?

Solution 1:

The > operator only redirects stdout ("standard output"), or "file descriptor 1". Error messages are usually printed on a different file descriptor, 2, stderr, ("standard error"). On your terminal screen, you are seeing both stdout and stderr.

The > operator is really more just a shortcut for 1>, and again, only redirects stdout. The 2> operator is similar to 1> but it instead of redirecting stdout, it redirects stderr.

user@host$ echo hello world >/dev/null
user@host$ echo hello world 1>/dev/null
user@host$ echo hello world 2>/dev/null
hello world
user@host$

So, to redirect both stdout and stderr to the same file, use >file 2>&1.

user@host$ echo hi 2>/dev/null 1>&2
user@host$

This says, "redirect the echo's stderr to /dev/null, and redirect stdout to stderr.

user@host$ curl --invalid-option-show-me-errors >/dev/null
curl: option --invalid-option-show-me-errors: is unknown
try 'curl --help' or 'curl --manual' for more information

user@host$ curl --invalid-option-show-me-errors 2>/dev/null
user@host$ 
user@host$ curl --invalid-option-show-me-errors >/dev/null 2>&1
user@host$ 

In modern Bash, you can also use &> to redirect both streams to the same file:

user@host$ curl --invalid-option-show-me-errors &>/dev/null
user@host$ 

So for you, specifically, use:

aws ec2 delete-snapshot --snapshot-id vid --output json >test 2>&1

Or

aws ec2 delete-snapshot --snapshot-id vid --output json &>test

Solution 2:

Error output will be written to stderr, not stdout, and you are only redirecting stdout. If you want to capture stderr as well, you need to add 2>&1, e.g.:

aws ec2 delete-snapshot --snapshot-id vid --output json >test 2>&1

Solution 3:

If you want to capture both stdout and stderr in a variable, try:

RESULT="$(aws ec2 delete-snapshot --snapshot-id vid --output json 2>&1)"

if ! [[ $RESULT =~ "Successfully deleted snapshot" ]]; then
  echo "ERROR while deleting snapshot"
  echo "$RESULT"
  exit 1
fi

...