Dieser Artikel stellt vor, wie man eine Eingabeaufforderung implementiert, die warnt, bevor der “rm -rf *“-Befehl auf der Befehlszeile in der Bash-Programmiersprache (Skriptsprache) für Linux-PCs und Server ausgeführt wird.
<>
rm -rf ist berühmt als einer der gefährlichsten Befehle
</>
Diesmal werde ich Code vorstellen, den ich mit der Idee geschrieben habe, die Gefahr des rm -rf-Befehls auch nur ein wenig zu reduzieren.
Verwendungsbeispiel

$ tmpdird # In neues Verzeichnis wechseln
$ ls
total 0
166351711236005864 drwxrwxrwx 1 yuis yuis 4096 Jul 10 21:59 ..
23080948093026057 drwxrwxrwx 1 yuis yuis 4096 Jul 10 21:59 .
$ genfiles 3 # Dateien generieren
$ ls
total 0
166351711236005864 drwxrwxrwx 1 yuis yuis 4096 Jul 10 21:59 ..
8444249304069546 -rwxrwxrwx 1 yuis yuis 2 Jul 10 21:59 3.txt
23080948093026057 drwxrwxrwx 1 yuis yuis 4096 Jul 10 21:59 .
51509920740553578 -rwxrwxrwx 1 yuis yuis 2 Jul 10 21:59 2.txt
36310271996515302 -rwxrwxrwx 1 yuis yuis 2 Jul 10 21:59 1.txt
$ rm -rf * # Alle Dateien löschen > Bestätigungsaufforderung > n
W: It seems You are attempting to run kind of dangerous command. Continue? [y/n]
n
$ ls # Bestätigen, dass Dateien nicht gelöscht wurden
total 0
166351711236005864 drwxrwxrwx 1 yuis yuis 4096 Jul 10 21:59 ..
8444249304069546 -rwxrwxrwx 1 yuis yuis 2 Jul 10 21:59 3.txt
23080948093026057 drwxrwxrwx 1 yuis yuis 4096 Jul 10 21:59 .
51509920740553578 -rwxrwxrwx 1 yuis yuis 2 Jul 10 21:59 2.txt
36310271996515302 -rwxrwxrwx 1 yuis yuis 2 Jul 10 21:59 1.txt
$ rm -rf * # Alle Dateien löschen > Bestätigungsaufforderung > y
W: It seems You are attempting to run kind of dangerous command. Continue? [y/n]
y
$ ls # Bestätigen, dass Dateien gelöscht wurden
total 0
166351711236005864 drwxrwxrwx 1 yuis yuis 4096 Jul 10 21:59 ..
23080948093026057 drwxrwxrwx 1 yuis yuis 4096 Jul 10 21:59 .
Wie oben gezeigt, erscheint eine Warnmeldung vor der Ausführung, wenn Sie versuchen, rm -rf * auszuführen. y führt es aus, und n bricht die Ausführung ab.
Code
ok(){
: <<< '
yes or no prompt
e.g. printf "The file alredy exist here. Override it? " ; ok && echo y || echo n
'
read -n 1 -r ; [[ $REPLY =~ ^[Yy]$ ]] && { echo ; return 0 ; } || { echo ; return 1 ; }
}
red='\e[1;31m'
grn='\e[1;32m'
yel='\e[1;33m'
blu='\e[1;34m'
mag='\e[1;35m'
cyn='\e[1;36m'
end='\e[0m'
warn(){
printf "${yel}W: ${*}\n${end}" >&2
}
##
shopt -s extdebug
preexec_invoke_exec () {
[ -n "$COMP_LINE" ] && return # do nothing if completing
[ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # don't cause a preexec for $PROMPT_COMMAND
local this_command=`HISTTIMEFORMAT= history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//"`;
# So that you don't get locked accidentally
if [ "shopt -u extdebug" == "$this_command" ]; then
return 0
fi
# // filtering
# Modify $this_command and then execute it
# eval "${this_command}"
# echo "${this_command}"
if [[ "${this_command}" =~ ^(somethingdangercommand$|somethingdangercommand[[:space:]]) ]]; then warn "It seems You are attempting to run kind of dangerous command. Continue? [y/n]" ; ok && eval "${this_command}" || return
elif [[ "${this_command}" =~ ^(anotherSomethingdangercommand$|anotherSomethingdangercommand[[:space:]]) ]]; then warn "It seems You are attempting to run kind of dangerous command. Continue? [y/n]" ; ok && eval "${this_command}" || return
elif [[ "${this_command}" =~ ^(rm[[:space:]][-rf]{3}$|rm[[:space:]][-rf]{3}[[:space:]]) ]]; then warn "It seems You are attempting to run kind of dangerous command. Continue? [y/n]" ; ok && eval "${this_command}" || return
else eval "${this_command}"
fi
# // filtering
return 1 # This prevent executing of original command
}
trap 'preexec_invoke_exec' DEBUG
Fügen Sie den obigen Code zu ${HOME}/.bashrc hinzu und versuchen Sie, einen undefinierten Befehl, somethingdangercommand, auszuführen. Da es sich um einen undefinierten Befehl handelt, würden Sie normalerweise einen Fehler erhalten, dass er undefiniert ist, aber durch Eingabe von n an der Eingabeaufforderung wird der Befehl selbst nicht ausgeführt, sodass er ohne Fehler beendet wird.
trap ‘preexec_invoke_exec’ DEBUG … Führe preexec_invoke_exec() vor jeder Befehlsausführung aus
elif [[ ”${this_command}” =~ ^(rm[[:space:]][-rf]{3}$|rm[[:space:]][-rf]{3}[[:space:]]) ]]; then warn “It seems You are attempting to run kind of dangerous command. Continue? [y/n]” ; ok && eval ”${this_command}” || return … Warnen, wenn der ausgeführte Befehl rm -rf oder rm -fr ist
Bevor ein Befehl ausgeführt wird, wird gefiltert, ob der Befehl mit einem regulären Ausdruck übereinstimmt usw., und wenn er vom Filter erfasst wird, warnt es; andernfalls wird der übergebene Befehl wie üblich mit eval ausgeführt.
Referenzen
- Linux trap command help and examples
- linux - Modify all bash commands through a program before executing them - Unix & Linux Stack Exchange
Fazit
Es scheint, dass rm -rf-Unfälle oft aufgrund von Ausrufezeichen-Expansion passieren. Wenn Sie es nicht verwenden, ist es gut, es zu deaktivieren.
# disable/turn off history expansion `!` altogether
set +H