Shell script & good way to prevent accidental Unix " rm -r * " : Linux & HP-UX


Can anyone provide a Shell script such that if

a) if the person issues "rm -r *", the script will check if the current directory
    is / or /var or /usr or /oracle (or any additional directories that I may add
    from time to time),  it will not echo out a message, you are about to execute
    a dangerous delete from `pwd` & then come back to command prompt

b) if the person issues "rm *" or "rm *.*", it will do a confirmation, whether
    to proceed besides echoing "Alert, you're in `pwd`, confirm to proceed? "


Any other way to prevent accidental deletion of files are welcome.

I'm concerned that if I replace the "rm" binary with the above "rm" script,
certain cron or jobs may fail
sunhuxAsked:
Who is Participating?
 
nanocosmCommented:
Ok, here's the announced bashrc script. Place it in the global or user .bashrc and make sure your users are using bash as  a shell.


myrm () {
    rm=`which rm`
    p=`pwd`
    pathes=( /root /etc /var )
    #echo "CurrentPath: $p"
    #echo "Array: ${pathes[@]:0}"
    #echo "Elements: $(seq 0 $((${#pathes[@]} -1)))"
    #echo "$1 $2 $3"

    #This is case a)
    #if the person issues "rm -r *", the script will check if the current directory
    #is / or /var or /usr or /oracle (or any additional directories that I may add
    #from time to time),  it will not echo out a message, you are about to execute
    #a dangerous delete from `pwd` & then come back to command prompt
    if [ "$1" == "-r" ]; then
        for i in $(seq 0 $((${#pathes[@]} -1)))
        do
            #echo "Elem: ${pathes[$i]}"
            if [ "${pathes[$i]}" == "$p" ]
            then
                return  # Just do nothing
            fi
        done
    fi

    #This is case b)
    #if the person issues "rm *" or "rm *.*", it will do a confirmation, whether
    #to proceed besides echoing "Alert, you're in `pwd`, confirm to proceed? "
    if [ "$1" == "*" ] || [ "$1" == "*.*" ]; then
        for i in $(seq 0 $((${#pathes[@]} -1)))
        do
            #echo "Elem: ${pathes[$i]}"
            if [ "${pathes[$i]}" == "$p" ]
            then
                echo "*** WARNING ***"
                echo ""
                echo "You are in a path that is dagerous to modify!"
                read -p "Type 'YES' to continue : " a
                if [ "$a" == "YES" ]; then
                    $rm $1 $2 $3 $4 $5 $6 $7 $8 $9
                fi
            fi
        done
    fi
}

alias rm="myrm"

Open in new window

0
 
TintinCommented:
On most Linux systems, rm is an alias to 'rm -i', which can be a great help in preventing the accidental deletion of files/dirs

Note that there is no simple way of detecting whether a user types in rm * as shell globbing will expand * to whatever files/dirs it matches.

0
 
nanocosmCommented:
If your default shell is for example bash, then you can assign an alias for rm. Cron usually has sh as the default shell and would not be affected by the alias.

Modify your profile (user or system wide) like this:
...
alias rm="rm -I"    (If you want to force to be asked when deleteing more than three files or recrusivly)
...

or for the bash script variant:
alias rm="PATH/TO/THE/BASHSCRIPT"


The korn shell script will be added shortly...
0
Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

 
arnoldCommented:
You could alternative replace the rm binary with a shell script that will evaluate what is being passed and then pass the command/argument to the rm.real $arguments.

#!/bin/sh
echo "$0 is the command"
echo "$1 is the first argument"
echo "$2 is the second item"

save this file locally as rmtest.sh
then run: ./rmtest.sh -r
0
 
advegaCommented:
The solution is not as simple as it seems because the rm utility is used also by other OS subsystems and to profanate them is not adviced.

Have you considered using a RESTRICTED shell?
0
 
TintinCommented:
nanocosm.

The line

if [ "$1" == "*" ] || [ "$1" == "*.*" ]; then

will only work if shell globbing is turned off, or the user types

rm '*'

or

rm '*.*'

Also, either with shell globbing on or off

$rm $1 $2 $3 $4 $5 $6 $7 $8 $9

will not remove the files matched by * or *.*

Additionally, you can easily get away with not using an array, by doing

paths="/root|/etc|/var"

if echo $PWD | grep -qE "$paths"
then
      ...
fi




0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.