Shell Script mktemp, was ist die beste Methode, um temporäre Named Pipe zu erstellen?

30

Ich bin mir bewusst, dass es am besten ist, temporäre Dateien mit zu erstellen mktemp, aber was ist mit Named Pipes?

Ich bevorzuge Dinge, die so POSIX-konform wie möglich sind, aber nur Linux ist akzeptabel. Das Vermeiden von Bashisms ist mein einziges hartes Kriterium, während ich schreibe dash.

JM Becker
quelle

Antworten:

41
tmppipe=$(mktemp -u)
mkfifo -m 600 "$tmppipe"

Im Gegensatz zur regulären Dateierstellung, bei der die Gefahr besteht, dass eine vorhandene Datei oder eine symbolische Verknüpfung sie überfällt, erstellt die Erstellung einer Namenspipe durch mkfifodie zugrunde liegende Funktion entweder eine neue Datei an der angegebenen Stelle oder schlägt fehl. So etwas : >fooist unsicher, denn wenn der Angreifer die Ausgabe vorhersagen mktempkann, kann er die Zieldatei für sich selbst erstellen. Aber mkfifo foowürde in einem solchen Szenario fehlschlagen.

Wenn Sie eine vollständige POSIX-Portierbarkeit benötigen, mkfifo -m 600 /tmp/myfifoist dies sicher gegen Entführung, aber anfällig für einen Denial-of-Service. Ohne Zugriff auf einen starken Zufallsgenerator für Dateinamen müssten Sie Wiederholungsversuche verwalten.

Wenn Sie sich nicht um die subtilen Sicherheitsprobleme bei temporären Dateien kümmern, können Sie eine einfache Regel befolgen: Erstellen Sie ein privates Verzeichnis, und bewahren Sie alles dort auf.

tmpdir=
cleanup () {
  if [ -n "$tmpdir" ] ; then rm -rf "$tmpdir"; fi
  if [ -n "$1" ]; then kill -$1 $$; fi
}
tmpdir=$(mktemp -d)
trap 'cleanup' EXIT
trap 'cleanup HUP' HUP
trap 'cleanup TERM' TERM
trap 'cleanup INT' INT
mkfifo "$tmpdir/pipe"
Gilles 'SO - hör auf böse zu sein'
quelle
Eigentlich habe ich mich gestern schon für diese Lösung entschieden. Ich habe darauf gewartet, ob jemand sie veröffentlicht hat oder eine bessere. Ich hatte auch das Gefühl, dass das Richtige für mich war. Egal ... Danke für die Hilfe, ich weiß es zu schätzen.
JM Becker
1
Sollte der Trap-Befehl nicht sein trap "rm -rf '$tempdir'" EXIT HUP INT TERM? Kann Trap seine eigene variable Expansion machen?
Sechs
@Six Ihr Befehl wird $tempdirzum Zeitpunkt der trapAuswertung des Befehls erweitert, nicht zum Zeitpunkt des Auslösens des Traps. In diesem Fall macht es keinen Unterschied, außer dass Ihr Code schrecklich kaputt geht, wenn der Wert von tempdirein einfaches Anführungszeichen enthält, während mein Code immer funktioniert.
Gilles 'SO- hör auf böse zu sein'
@ Gilles Das ist eine nette Funktion. Ich hatte Ihr Beispiel mit einfachen Anführungszeichen ohne Glück ausprobiert und dachte, Trap könne zur Laufzeit keine Variablen auswerten. Es stellte sich heraus, dass my $tempdirlokal deklariert wurde und global definiert werden muss, damit trap darauf zugreifen kann. Macht jetzt Sinn ...
Sechs
1
@Gilles ... solange sich der $tempdir Wert nicht ändert, was grundsätzlich für alle Zwecke akzeptabel ist. Achten Sie nur darauf, nicht denselben Namen zu verwenden, um mehrere temporäre Dateien / Verzeichnisse zu erstellen ...
MestreLion
3

Eine sicherere Alternative ist es mktemp, ein Verzeichnis sicher zu erstellen, dann die Named Pipe in dieses Verzeichnis zu setzen und rm -R $dires am Ende zu entfernen.

David Parks
quelle
Ich habe mich entschieden, das FIFO in einem mktempVerzeichnis zu erstellen , da dies die einzig akzeptable Antwort war. Nur für den Fall, dass Sie es nicht bemerkt haben, hat @Gilles diese Antwort bereits ausführlich gepostet.
JM Becker
2

Verwenden Sie die Option "Trockenlauf":

mkfifo $(mktemp -ut pipe.XXX)
Polemon
quelle
1
Laut den Manpages wird die Verwendung der -uOption "nicht empfohlen".
Dogbane
@dogbane Also ist die Verwendung von -t, aber solange es zuverlässig funktioniert, würde ich damit gehen.
Polemon
Entschuldigung, wo steht, dass -tdavon abgeraten wird?
Dogbane
2
@dogbane Wenn es in irgendeiner Weise kritisch ist, würde ich eine winzige C-Anwendung erstellen, die die mkstemp()Funktion aufruft ( linux.die.net/man/3/mkstemp ). Der -tSchalter ist nicht entmutigt, es ist -pmein schlechtes.
Polemon
1

Sie können verwenden mktemp eine temporäre Datei erstellen, diese dann löschen und eine Named Pipe mit demselben Namen erstellen.

Beispielsweise:

TMPPIPE=$(mktemp -t pipe.XXX) && {
    rm -f $TMPPIPE
    mkfifo $TMPPIPE
}
Dogbane
quelle
Ist das Löschen der $TMPPIPEvor dem mkfifoVermeiden Sie die ‚unsicher‘ Problem, das zu tun TMPPIPE=`mktemp -u` ; mkfifo $TMPPIPE?
JM Becker
1
@TechZilla mkfifoist im Gegensatz zur normalen Dateierstellung über die Shell tatsächlich sicher. Wenn dies nicht der Fall wäre, würde das Erstellen und Löschen einer Datei überhaupt nicht helfen (tatsächlich würde dies die Arbeit des Angreifers erheblich erleichtern, da er den Dateinamen nicht erraten muss). Die Antwort von dogbane funktioniert also, aber die Zwischenerstellung von Dateien ist eine nutzlose Komplikation.
Gilles 'SO- hör auf böse zu sein'
1
@ Gilles, weißt du in welcher Hinsicht die mktempManpage die -uOption 'unsicher' genannt hat?
JM Becker
@dogbane, ich habe über Ihre Antwort abgestimmt, und Ihre Kommentare, die ich für solide hielt. Obwohl ich dies gestern bereits abgeschlossen habe. Ich habe nur darauf gewartet, ob jemand meine oder hoffentlich eine bessere Lösung veröffentlicht hat. Also, obwohl ich mktemp -ddich benutzt habe, hast du immer noch ein paar Punkte für deine Eingabe. Vielen Dank für all Ihre Hilfe, ich weiß das sehr zu schätzen!
JM Becker
1
@TechZilla mktemp -uist beim Erstellen einer regulären Datei nicht sicher, da es den Schutz vor Denial-of-Service bietet (wenn der von ihm generierte Name nicht vorhersehbar genug ist), aber einen Angreifer nicht daran hindert, die Datei unter der Nase des Programms zu erstellen. Das Erstellen eines FIFO anstelle einer regulären Datei ist ein seltener Anwendungsfall, den die Manpage nicht behandelt.
Gilles 'SO- hör auf böse zu sein'
0

Verwenden Sie mkfifooder mknodin Unix, wo zwei separate Prozesse über den Namen auf die Pipe zugreifen können - ein Prozess kann sie als Leser und der andere als Schreiber öffnen.

mkfifo my_pipe
gzip -9 -c < my_pipe > out.gz
cat file > my_pipe

Die Named Pipe kann wie jede andere Datei gelöscht werden:

rm my_pipe

mkfifo --mode=0666 /tmp/namedPipe
gzip --stdout -d file.gz > /tmp/namedPipe

NamedPipe kann als reguläre Datei nur zum einmaligen Lesen verwendet werden.

http://www.linuxjournal.com/article/2156

Nikhil Mulley
quelle
2
Ich bin mir der Named Pipes voll bewusst und mkfifo. Meine Frage zu temporären Named Pipes wird nicht mehr beantwortet , als mkdirdas Erstellen temporärer Verzeichnisse.
JM Becker
2
Wie werden die Probleme behoben, mktempdie beim sicheren Erstellen einer Named Pipe auftreten?
Camh
1
oh ok, am besten erstelle sie unter / tmp, sie sind per definitionem temporäre Dateien und werden gelöscht, sobald das System neu gestartet wird. Oder noch besser, haben Sie eine Shell-Funktion, die die namedpipe aus dem mktempErgebnis selbst erzeugt (natürlich, indem Sie zuerst die temporäre Datei löschen und dann mkfifoauf derselben ausführen ). mktempkann auch verwendet werden, um ein temporäres Verzeichnis zu erstellen. Versuchen Sie es mit -t -dswitch.
Nikhil Mulley