Home > Software design >  How to capture errors from running "gcloud app deploy" into a variable (Bash)
How to capture errors from running "gcloud app deploy" into a variable (Bash)

Time:04-25

I am deploying my application to GCP via bash script. I want to capture any deployment errors in a variable and perform some actions when a deployment error occurs.

My deployment command looks like this:

gcloud app deploy --version $version --project my-app-$environment $micro.yaml --quiet $no_promote &

You can assume that this command is working with the variables I've passed. I've tried the below variations:

  1. var=$(...)

    var=$(gcloud app deploy --version $version --project my-app-$environment $micro.yaml --quiet $no_promote &)

    echo ******************************
    echo "${var}"
    echo ******************************

  2. var=`...`

    var=`gcloud app deploy --version $version --project my-app-$environment $micro.yaml --quiet $no_promote &`

    echo ******************************
    echo $var
    echo ******************************

Other variations from GCP side that I've tried:

  1. --verbosity="warning"

    var=$(gcloud app deploy --version $version --project my-app-$environment $micro.yaml --quiet $no_promote --verbosity="warning" &)

  2. --verbosity="error"

    var=$(gcloud app deploy --version $version --project my-app-$environment $micro.yaml --quiet $no_promote --verbosity="error" &)

  3. --log-http

    var=$(gcloud app deploy --version $version --project my-app-$environment $micro.yaml --quiet $no_promote --log-http &)

  4. --user-output-enabled

    var=$(gcloud app deploy --version $version --project my-app-$environment $micro.yaml --quiet $no_promote --user-output-enabled &)

Everything that I've tried so far, $var is always returned empty. Even when there's an error during deployment.

╔════════════════════════════════════════════════════════════╗
╠═ Uploading 0 files to Google Cloud Storage                ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
ERROR: (gcloud.app.deploy) ABORTED: Cannot operate on apps/my-app-qa/services/search/versions/1 because an operation is already in progress for apps/my-app-qa/services/search/versions/1 by 3458c670-76bd-42ec-a971-c0ceda7ef34f.
******************************    
    
******************************

Is there a way to detect a GCP deployment error when the deployment happens through bash script? Seems like I am missing something really basic but can't put my finger to it.

CodePudding user response:

Update: What I've written below still holds, but I missed the main problem: you try to run the gcloud tool in the background (via the & at the end of its command line), which means that call returns immediately, before the $() construct has a chance to capture anything.

What you are essentially doing is to assign the command's output to your variable before the command actually has a chance to output anything. So you have basically two options:

Option 1: run the command in the foreground and continue with your script once it has finished. If the command is running for a long time and the "backgrounding" was intentional, this obviously won't work.

Option 2: run the command in the background, redirect its stderr to a file (see below) and then actively monitor that file for changes (i.e. errors). That's certainly mire involved and the concrete way to do it depends a lot on what exactly you want your script to do.

Original Answer: I'm not familiar with the gcloud tool in particular, but I assume it prints its error messages to stderr (as is the convention for commandline tools). The $(command) construct captures stdout, so you get everything except the errors.

To solve this you have to redirect stderr in your gcloud call:

var=$(gcloud --options 2>&1)

The 2>&1 tells the nested shell spawned by the $() construct to redirect (>) the output stream #2 (= stderr) to the same location (&) as stream #1 (= stdout), causing it to be captured into your variable.

Since you likely want to capture only stderr, you also need to get rid of stdout:

var=$(gcloud --options 2>&1 >/dev/null)

The >/dev/null redirects the default stream (= stderr) into the void.

An alternative if you want to both display the command output and capture its errors is to pipe stderr into tee (tool that prints the input and saves a copy to a file) and then read the captured error file into your variable:

gcloud --options 2| tee /tmp/my-gcloud-errors
var=$(cat /tmp/my-gcloud-errors)

(answer may contain errors, since I'm typing this on my phone with a cat on my lap. Will fix later)

  • Related