metersk
metersk

Reputation: 12519

How to intercept/evaluate a shell command, run logic on the command and potentially kill the command

There is a command line tool at my company that many people will use, but we need to set some restrictions on the tool's usage based on the environment that the user is in.

For example, if the user is logged into our production environment and they run dbt run <some more flags>, I need to flash a warning and prompt them to continue or exit.

I use zsh myself and found the preexec() hook, but unfortunately, because of the way this is implemented, calling exit kills the whole shell and closes the terminal. This seems to be a non-starter for this option.

I'm looking for a pure bash alternative (many of my coworkers may not use zsh) that will allow me to evaluate a command before it's executed, run the command through some logic, and allow me to either kill the command or run it.

Here is the zsh function i wrote for reference:

preexec() {
  command=$1
  first_seven_chars=${command:0:7}

  if [[ "$first_seven_chars" != "dbt run" ]]; then return; fi

  if [[ "$AWS_ENVIRONMENT" != "production" ]]; then return; fi

  if [[ "$AWS_ENVIRONMENT" = "production" ]]; then 
    read -k1 -s "key?WARNING: You are in Production. Do you want to continue? Enter y to continue or any key to exit"
    
    if [[ "$key" = "y" ]]; then
      echo "Continuing in Production..."
      
      BRANCH=$(git rev-parse --abbrev-ref HEAD)
      if [[ "$BRANCH" != "master" ]]; then
        echo 'You are currently not on the master branch. To prevent models and data deviating, please merge your changes into master and rerun';
        exit;
      fi
    else
      echo "\n"
      echo "\nStopping command from running in production..."
      exit;
    fi
    exit;
  fi 
}

Note: I realize https://github.com/rcaloras/bash-preexec exists, but since it mirrors the zsh functionality it might not be the best to use.

Upvotes: 1

Views: 1012

Answers (1)

HappyFace
HappyFace

Reputation: 4103

What you need to do is create a wrapper around the original command, not mess with preexec and other shell-specific hooks. Of course, you can write this wrapper itself as a zsh script. So you'll create, e.g., dbt_safe.zsh which would internally call dbt, and your colleagues would just use dbt_safe.zsh.

Upvotes: 1

Related Questions