Shell Script mktemp, jaka jest najlepsza metoda tworzenia tymczasowej nazwanej potoku?

30

Wiem, że najlepiej jest tworzyć pliki tymczasowe mktemp, ale co z nazwanymi potokami?

Wolę, aby rzeczy były jak najbardziej zgodne z POSIX, ale tylko Linux jest akceptowalny. Unikanie bashism jest moim jedynym trudnym kryterium, kiedy piszę dash.

JM Becker
źródło

Odpowiedzi:

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

W przeciwieństwie do zwykłego tworzenia pliku, który jest podatny na przejęcie przez istniejący plik lub dowiązanie symboliczne, utworzenie potoku nazw przez mkfifolub podstawową funkcję albo tworzy nowy plik w określonym miejscu, albo kończy się niepowodzeniem. Coś takiego : >foojest niebezpieczne, ponieważ jeśli osoba atakująca może przewidzieć wynik, mktemposoba atakująca może utworzyć plik docelowy dla siebie. Ale mkfifo foozawiodłby w takim scenariuszu.

Jeśli potrzebujesz pełnej przenośności POSIX, mkfifo -m 600 /tmp/myfifojest bezpieczny przed przejęciem, ale jest podatny na odmowę usługi; bez dostępu do silnego generatora losowych nazw plików konieczne byłoby zarządzanie próbami ponownych prób.

Jeśli nie przejmujesz się subtelnymi problemami związanymi z bezpieczeństwem plików tymczasowych, możesz postępować zgodnie z prostą zasadą: utwórz prywatny katalog i przechowuj wszystko.

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- przestań być zły”
źródło
Właściwie już wczoraj wybrałem to jako swoje rozwiązanie, czekałem, czy ktoś to opublikuje, lub lepsze. W moim przypadku również czułem, że reż. Niezależnie ... Dziękuję za pomoc, doceniam to.
JM Becker,
1
Czy nie powinno być poleceniem pułapki trap "rm -rf '$tempdir'" EXIT HUP INT TERM? Czy pułapka może mieć własną zmienną ekspansję?
Sześć
@ Sześć Twoje polecenie rozszerzy się $tempdirw momencie jego trapoceny, a nie w momencie wyzwolenia pułapki. W tym przypadku nie robi to żadnej różnicy, z wyjątkiem tego, że Twój kod psuje się okropnie, jeśli wartość tempdirzawiera pojedynczy cudzysłów, podczas gdy mój kod zawsze działa.
Gilles „SO- przestań być zły”
@Gilles To miła funkcja. Próbowałem twojego przykładu z jednym cytatem bez powodzenia, więc pomyślałem, że pułapka nie jest w stanie ocenić zmiennych w czasie wykonywania. Okazało się, że mój $tempdirzostał zadeklarowany lokalnie i musi być zdefiniowany globalnie, aby pułapka miała do niego dostęp. Ma to teraz sens ...
Szósty
1
@Gilles ... dopóki $tempdir wartość się nie zmienia, co jest dopuszczalne do wszystkich celów. Uważaj tylko, aby nie używać tej samej nazwy do tworzenia wielu plików tymczasowych / katalogów ...
MestreLion 15.01.2016
3

Bezpieczniejszą alternatywą jest bezpieczne mktemputworzenie katalogu, a następnie umieszczenie nazwanego potoku w tym katalogu, a rm -R $dirna końcu pozbycie się go.

David Parks
źródło
Zdecydowałem się stworzyć FIFO w mktempkatalogu, ponieważ była to naprawdę jedyna akceptowalna odpowiedź. Na wypadek, gdybyś nie zauważył, @Gilles już opublikował tę odpowiedź dogłębnie.
JM Becker,
2

Użyj opcji „rozruchu na sucho”:

mkfifo $(mktemp -ut pipe.XXX)
polemon
źródło
1
Według stron man użycie -uopcji „nie jest zalecane”.
dogbane
@dogbane Tak jest wykorzystanie -t, ale tak długo, jak działa niezawodnie, pójdę z tym.
polemon 24.01.12
przepraszam, gdzie to mówi, że -tjest to zniechęcone?
dogbane
2
@dogbane Jeśli jest to w jakikolwiek sposób krytyczne, stworzę małą aplikację C, wywołującą mkstemp()funkcję ( linux.die.net/man/3/mkstemp ). Zmiana -tnie jest zniechęcona, to jest -pmoje złe.
polemon 24.01.12
1

Możesz użyć mktempdo utworzenia pliku tymczasowego, a następnie go usunąć i utworzyć nazwany potok o tej samej nazwie.

Na przykład:

TMPPIPE=$(mktemp -t pipe.XXX) && {
    rm -f $TMPPIPE
    mkfifo $TMPPIPE
}
dogbane
źródło
Czy usunięcie $TMPPIPEwcześniej pozwala mkfifouniknąć związanego z tym „niebezpiecznego” problemu TMPPIPE=`mktemp -u` ; mkfifo $TMPPIPE?
JM Becker
1
@TechZilla mkfifojest w rzeczywistości bezpieczny, w przeciwieństwie do zwykłego tworzenia plików z powłoki. Jeśli tak nie jest, utworzenie pliku, a następnie usunięcie go wcale nie pomogłoby (w rzeczywistości znacznie ułatwiłoby atakującemu zadanie, nie wymagając od niego odgadnięcia nazwy pliku). Tak więc odpowiedź dogbane działa, ale tworzenie pliku pośredniego jest bezużyteczną komplikacją.
Gilles 'SO - przestań być zły'
1
@Gilles, czy wiesz, pod jakim względem mktempstrona podręcznika man nazywa -uopcję „niebezpieczna”?
JM Becker,
@dogbane, głosowałem za twoją odpowiedzią, a twoje komentarze, które uważałem za solidne. Chociaż ukończyłem to już wczoraj. Po prostu czekałem, aż ktoś opublikuje albo moje rozwiązanie, albo, mam nadzieję, lepsze. Więc nawet jeśli użyłem mktemp -d, wciąż masz trochę punktów za swój wkład. Dziękuję za całą pomoc, naprawdę to doceniam!
JM Becker,
1
@TechZilla mktemp -ujest niebezpieczny podczas tworzenia zwykłego pliku, ponieważ zapewnia ochronę przed odmową usługi (jeśli generowana nazwa jest wystarczająco nieprzewidywalna), ale nie uniemożliwia atakującemu utworzenia pliku pod nosem programu. Tworzenie fifo zamiast zwykłego pliku to rzadki przypadek użycia, którego strona man nie adresuje.
Gilles „SO- przestań być zły”
0

Użyj mkfifolub mknodw Uniksie, gdzie dwa oddzielne procesy mogą uzyskać dostęp do potoku według nazwy - jeden proces może otworzyć go jako czytnik, a drugi jako pisarz.

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

Nazwany potok można usunąć tak jak każdy plik:

rm my_pipe

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

NamedPipe może być używany jako zwykły plik do odczytu tylko raz.

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

Nikhil Mulley
źródło
2
Jestem w pełni świadomy nazwanych potoków i mkfifo. Nie odnosi się do mojego pytania dotyczącego tymczasowych nazwanych potoków, bardziej niż mkdirdotyczy tworzenia tymczasowych katalogów.
JM Becker
2
W jaki sposób rozwiązuje to problemy mktempdotyczące bezpiecznego tworzenia nazwanego potoku?
camh
1
o ok, najlepiej jest utworzyć je w katalogu / tmp, z definicji są to pliki tymczasowe i zostaną usunięte po ponownym uruchomieniu systemu. Lub jeszcze lepiej, mieć funkcję powłoki, która utworzy nazwaną rurę na podstawie mktempsamego wyniku (oczywiście najpierw usuwając plik tymczasowy, a następnie działając mkfifona tym samym). mktempmożna również użyć do utworzenia katalogu tymczasowego, spróbuj z -t -dprzełącznikiem.
Nikhil Mulley