Der entscheidende Teil ist, dass ich den Umfang des Problems reduziere: Ich verbiete die indirekte Ausführung des Skripts über den Pfad (wie in /bin/sh [script path relative to path component]
).
Dies kann festgestellt werden, weil $0
wird ein relativer Pfad sein, der nicht auf eine Datei relativ zum aktuellen Ordner verweist. Ich glaube, dass die direkte Ausführung mit der Option #!
Mechanismus führt immer zu einer absoluten $0
auch wenn das Skript im Pfad gefunden wird.
Ich verlange auch, dass der Pfadname und alle Pfadnamen entlang einer Kette von symbolischen Links nur eine vernünftige Teilmenge von Zeichen enthalten, insbesondere nicht \n
, >
, *
o ?
. Dies ist für die Parsing-Logik erforderlich.
Es gibt noch einige weitere implizite Erwartungen, auf die ich nicht eingehen werde (siehe diese Antwort ), und ich versuche nicht, die vorsätzliche Sabotage von $0
(berücksichtigen Sie also alle Sicherheitsaspekte). Ich erwarte, dass dies auf fast jedem Unix-ähnlichen System mit einem Bourne-ähnlichen /bin/sh
.
#!/bin/sh
(
path="${0}"
while test -n "${path}"; do
# Make sure we have at least one slash and no leading dash.
expr "${path}" : / > /dev/null || path="./${path}"
# Filter out bad characters in the path name.
expr "${path}" : ".*[*?<>\\]" > /dev/null && exit 1
# Catch embedded new-lines and non-existing (or path-relative) files.
# $0 should always be absolute when scripts are invoked through "#!".
test "`ls -l -d "${path}" 2> /dev/null | wc -l`" -eq 1 || exit 1
# Change to the folder containing the file to resolve relative links.
folder=`expr "${path}" : "\(.*/\)[^/][^/]*/*$"` || exit 1
path=`expr "x\`ls -l -d "${path}"\`" : "[^>]* -> \(.*\)"`
cd "${folder}"
# If the last path was not a link then we are in the target folder.
test -n "${path}" || pwd
done
)
91 Stimmen
Keine der derzeitigen Lösungen funktioniert, wenn es irgendwelche Zeilenumbrüche am Ende des Verzeichnisnamens - Sie werden von der Befehlssubstitution entfernt. Um dies zu umgehen, können Sie ein Nicht-Neuzeilen-Zeichen innerhalb der Befehlsersetzung anhängen -
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd && echo x)"
- und entfernen Sie es ohne Befehlssubstitution -DIR="${DIR%x}"
.94 Stimmen
@jpmc26 Es gibt zwei sehr häufige Situationen: Unfälle und Sabotage. Ein Skript sollte nicht auf unvorhersehbare Weise versagen, nur weil jemand, irgendwo, eine
mkdir $'\n'
.36 Stimmen
Wer Leute sein System auf diese Weise sabotieren lässt, sollte es nicht der Bash überlassen, solche Probleme zu erkennen... und schon gar nicht Leute einstellen, die zu solchen Fehlern fähig sind. Ich habe in den 25 Jahren, in denen ich die Bash benutze, noch nie erlebt, dass so etwas irgendwo passiert.... Deshalb gibt es Dinge wie Perl und Praktiken wie Taint Checking (ich werde wahrscheinlich dafür geflamed werden, dass ich das sage :)
79 Stimmen
Ich empfehle Ihnen, dies zu lesen Bash FAQ über das Thema.
0 Stimmen
"${PWD%/}/application"