Zaczynam w pustym katalogu.
$ touch aFile
$ ls
aFile
Następnie mam ls
dwa argumenty, z których jeden nie znajduje się w tym katalogu. Przekierowuję oba strumienie wyjściowe do pliku o nazwie output
. Używam >>
, aby uniknąć pisania jednocześnie.
$ ls aFile not_exist >>output 2>>output
$ cat output
ls: cannot access 'not_exist': No such file or directory
aFile
Co wydaje się działać. Czy są jakieś niebezpieczeństwa związane z tym podejściem?
io-redirection
stdout
stderr
exit_status
źródło
źródło
ls aFile not_exist &>>output
tutaj bardziej standardowego ? (Uwaga,&>>
NIE jest standardem. Jest to DEPRECATED, niejednoznaczna składnia, która działa inaczej w różnych powłokach. Zastanawiam się, skąd macie swoje rzeczy.ls &>>foo ...
powinny być analizowane jako dwa comandsls &
i>>foo ...
, a to jest droga inne muszle jakby/bin/sh
od Ubuntu są analizowania go. Ponieważ jest przestarzałe, możesz zajrzeć tutaj - chociaż nie udaję, że to jakikolwiek autorytet. Możesz jednak zapytaćbash
opiekunów, czy uważają to za dobry pomysł.Odpowiedzi:
Nie, to nie jest tak bezpieczne jak standard
>>bar 2>&1
.Kiedy piszesz
otwierasz
bar
plik dwa razyO_APPEND
, tworząc dwa całkowicie niezależne obiekty pliku [1], każdy z własnym stanem (wskaźnik, tryby otwarte itp.).Jest to bardzo odmienne od tego,
2>&1
które wywołuje tylko wywołaniedup(2)
systemowe i sprawia, że stderr i stdout są wymiennymi aliasami dla tego samego obiektu pliku.Jest z tym problem:
Zazwyczaj można liczyć na prawdopodobieństwo pliku jak
bar
wfoo >>bar 2>&1
zapisywany jest w tym samym czasie z dwóch różnych miejscach jest dość niska. Ale dzięki swojemu>>bar 2>>bar
zwiększyłeś go o kilkanaście rzędów wielkości, bez żadnego powodu.[1] „Otwórz opisy plików” w języku POSIX.
źródło
O_APPEND
jest trochę badziewny - dość uciążliwy do prawidłowego wdrożenia.O_APPEND
, klient najpierw pobierze „prawdziwy” rozmiar pliku z serwera („ponownie zweryfikuje” i-węzeł), a następnie dokona aktualizacji i-węzła seek + write + z pamięci podręcznej, a tylko ostatnia część jest wykonywane pod blokadami, co oznacza, że pierwsza część nadal może pobrać przestarzały rozmiar z serwera i zastąpić poprawny z lokalnego węzła / pamięci podręcznej. Ten sam problem zlseek(SEEK_END)
.Co się stanie, kiedy to zrobisz?
jest to, że
file
zostanie otwarte do dodawania dwa razy. Można to bezpiecznie zrobić w systemie plików POSIX. Każdy zapis, który stanie się z plikiem, gdy zostanie otwarty w celu dołączenia, nastąpi na końcu pliku, niezależnie od tego, czy dane przechodzą przez standardowy strumień wyjściowy, czy standardowy strumień błędów.Zależy to od obsługi operacji zapisu z dołączaniem atomowym w bazowym systemie plików. Niektóre systemy plików, takie jak NFS, nie obsługują dołączania atomowego. Zobacz np. Pytanie „Czy plik dołącza atom w systemie UNIX?” Na StackOverflow.
Za pomocą
działałby nawet na NFS.
Jednak za pomocą
nie jest bezpieczne, ponieważ powłoka obetnie plik wyjściowy (dwukrotnie), a każde zapisanie w jednym ze strumieni spowoduje zastąpienie danych już zapisanych przez inny strumień.
Przykład:
hello
Ciąg jest napisany pierwszy (z kończącego znaku nowej linii), a następnie ciągabc
następuje linii jest napisane z błędem standardowym, zastępowaniehell
. Wynikiem jest ciągabc
z nową linią, po której następuje resztka pierwszegoecho
wyniku,o
oraz nowa linia.Zamiana dwóch
echo
wokół rany produkuje tylkohello
w pliku wyjściowym, ponieważ ten ciąg jest zapisywany jako ostatni i jest dłuższy niżabc
ciąg. Kolejność przekierowań nie ma znaczenia.Lepiej i bezpieczniej byłoby używać bardziej idiomatycznych
źródło
>>
pochodzi), gdzie>>
można by je pisać i szukać do końca (przypuszczam, ponieważ O_APPEND nie było jeszcze wtedy wynalezione). Nawet w systemie Solaris 10/bin/sh -c '(echo a; echo b >&2) >> file 2>> file; cat file'
wyjściab
.sh
lub systemem plików Solaris 10 ?>>
pierwotnie robił, nie otwierał się z O_APPEND, otwierał się bez i szukał do końca. Nie jest to aż tak duży problem, tylko to, co robił i co zostało udokumentowane.To zależy od tego, co chcesz osiągnąć. To Ty decydujesz, czy możesz mieć błędy w tym samym pliku, co wynik. To jest po prostu zapisywanie tekstu w pliku z funkcjonalnością powłoki, która pozwala na przekierowanie, jak chcesz. Nie ma absolutnego tak lub nie. Jak wszystko w Linuksie można to zrobić na kilka sposobów, to jest mój sposób
ls notExistingFile existingFile >> output 2>&1
Aby odpowiedzieć na pytanie: Jeśli chodzi o samo przekierowanie, tak jest całkowicie bezpieczne.źródło
>
zamiast>>
zastąpi niektóre znaki. Więc nie chodzi tylko o to, że powłoka pozwala mi przekierowywać, ponieważ kiedy przekierowuję za pomocą>
, rezultat jest inny. Są więc niuanse>
, czy są jakieś>>
?>
- nadpisania.>>
- dołącz