This is based on another question of mine I am trying to prevent executions of certain commands using a script. I got the script to work perfectly in interactive shells but for non interactive shells it doesn't prevent its execution. I did see this and I am doing the same thing.

/home/user/stop.sh (sourced in .bashrc)

#!/usr/bin/env bash
shopt -s extdebug; stop_cmd () {
    [ -n "$COMP_LINE" ] && return  # not needed for completion
    [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # not needed for prompt
    local this_command=$BASH_COMMAND;
    echo $this_command" Not Allowed";
    return 1
trap 'stop_cmd' DEBUG


#!/usr/bin/env bash

I used the BASH_ENV variable suggested by @Inian to get my script into script files that use non-interactive shells.

In a new shell

#:export BASH_ENV=/home/user/stop.sh
ls Not Allowed --> This is because of the source in .bashrc
#:             --> Prompt appears. ls did not run
./temp.sh: /usr/share/bashdb/bashdb-main.inc: No such file or directory
./temp.sh: warning: cannot start debugger; debugging mode disabled
ls Not Allowed  --> Because of the $BASH_ENV
Directory contents displayed  --> ls ended up running
#:             --> Prompt appears after executing temp.sh

But this behavior is not displayed if I source stop.sh within temp.sh directly and it works like a charm.

  • 1
    Please don't crosspost. – chepner Feb 7 '18 at 21:08
  • @chepner Sorry about that. I started off there... But I saw that there was a similar effort answered here and hence I linked them – Sam Thomas Feb 7 '18 at 21:10
  • whoever downvoted this great job! I cant seem to get answers anywhere. Thanks for making it worse. – Sam Thomas Feb 8 '18 at 6:42
  • Can you run your script with bash -i? – cuonglm Feb 8 '18 at 6:45
  • @cuonglm Well I would.. But i can't expect people who make scripts to do that. And that's why I am trying to do this. Thank you for reading my email :) – Sam Thomas Feb 8 '18 at 6:47

I am afraid it is not possible to restrict command execution with the DEBUG trap within non-interactive shell.

Alternatively you can try different approaches:

Restriction with rbash, BASH_ENV and command_not_found_handle

  • Setup a test user
  • Symlink the allowed commands within test-users homedir


allow=(bash cat sed)
mkdir "$homedir/bin"
for c in ${allow[@]}; do
  ln -s /bin/$c $homedir/bin
  • Set the PATH variable in /home/$user/.bashenvrc and ensure that it only lists bindirs you want to allow, for example /home/$user/bin;...;...
  • Set BASH_ENV=/home/$user/.bashenvrc from /home/$user/.bashrc
  • Use a restricted shell via bash -r so the user cannot execute command names containing slashes, for example /bin/sh.

But keep the rbash security weaknesses in mind.

You want more fine grained restriction possibilities? You could extend this method with the command_not_found_handle () function, so every command which is not found in PATH can be handled in detail.

function command_not_found_handle () {
  while read -r pattern; do
    [[ "$1" =~ $pattern ]] \
    && command="/bin/restrict/$1" \
    && [ -h $command -a -x $command ] \
    && shift \
    && { $command "$@"; return $?; }
  done </bin/restrict/whitelist
  echo "Command '$1' not found."

Restriction with rbash, blacklist and wrappers

  • Setup a blacklist as root


cat <<EOF >/home/cmd_blacklist
  ~/bin/ls -al
  ~/bin/rm -rf
chmod g-wx+r,o-wx+r /home/cmd_blacklist
  • Add BASH_ENV=~/.bashenvrc to ~/.bashrc
  • Edit ~/.bashenvrc


errmsg='arguments not allowed: $cmd $pattern'
while read -r cmd pattern; do
  [ ! -e "$cmd" ] && continue # skip nonexistent
  [ "$cmd" == "$(basename $cmd)" ] && continue  # prevent recursion
  eval "function $(basename $cmd) () { [[ \"$(printf $'%s ' \$@)\" =~ $pattern ]] && echo \"$errmsg\" || $cmd \"\$@\"; }"
done </home/cmd_blacklist

Now every line of blacklist of the form [cmd] [pattern] should be read, from which wrapper functions are generated. You could also export the wrapper functions to subshell

Further reading and straightforward method with sudo

For many cases editing the sudoers configuration to restrict command execution is the best choice.

| improve this answer | |
  • Well I thought of that already.. moreover If I was to take this approach I would just add users to groups who can run this script right... but my requirement is more fine grained.. for eg: if some one runs ls I will permit it. But if some one runs ls -al I don’t want to.. for this I need to study the entire command carefully and compare against a text file that have certain rules... and hence the need for this.. I hope some one can answer this – Sam Thomas Feb 8 '18 at 6:33
  • But in my above comment ls will be in PATH i just dont want ls -al to be run (running ls by itself is fine).. Using the edited approach will I not be force to have an empty PATH so that every command goes through this handle? Also I do not want to give them a notion that command is not present in PATH. A person could easily install ls into that PATH. – Sam Thomas Feb 8 '18 at 8:06

Not the answer you're looking for? Browse other questions tagged or ask your own question.